< À la découverte d'Unicode

Si chaque caractère peut être représenté à travers les points de code définis par le répertoire Unicode, l'informatique nécessite de leur attribuer en plus d'un numéro, une représentation binaire.

Si l'on pourrait s'attendre à ce qu'Unicode définisse un multiplet suffisamment large pour représenter chacun des points de code Unicode, pour des raisons historiques, la réalité est toute autre.

En pratique, il est souvent nécessaire de représenter ces points de code dans des unités définies préalablement à une époque où l'on pensait que huit ou seize bits seraient largement suffisants.

Pour être traités informatiquement, les points de code (qui définissent des caractères) doivent être représentables par une séquence de bits et/ou d'octets. Ceci est rendu possible au travers des systèmes de codage de caractères attribuant à chaque point de code une séquence d'unités de code.

En dehors de la Chine populaire, les codages de caractères les plus utilisés sont sans doute l'UTF-8 et l'UTF-16, dont nous donnons quelques notions ci-après.

Les autres codages existant sont les suivants : UTF-7; UTF-8; CESU-8; UCS-2; UTF-16; UTF-32 (UCS-4); UTF-EBCDIC; SCSU; Punycode; GB 18030;

UTF-8

Le répertoire Unicode peut contenir plus d'un million de caractères, ce qui est bien trop grand pour être codé par un seul octet (limité à des valeurs entre 0 et 255). Techniquement, il s'agit de coder les caractères Unicode sous forme de séquences de un à quatre codet de un octet chacun.

Par exemple le caractère "€" (euro) est le 8365e caractère du répertoire Unicode, son index, ou point de code est donc 8364 (on commence à compter à partir de 0).

La principale caractéristique d'UTF-8 est qu'elle est rétro-compatible avec la norme ASCII 7 bits, c'est-à-dire que tout caractère ASCII se code en UTF-8 sous forme d'un unique octet, identique au code ASCII. Par exemple "A" (A majuscule) a pour code ASCII 65 et se code en UTF-8 par l'octet 65. Cela ne s'applique qu'aux textes en anglais, car toutes les autres langues utilisent des lettres avec diacritiques, ou carrément un autre alphabet que latin. Chaque caractère dont le point de code est supérieur à 127 (caractère non ASCII) se code sur 2 à 4 octets. Le caractère "€" (euro) se code par exemple sur 3 octets : 226, 130, et 172.

Codage UTF-8

Le principe du codage UTF-8 est d'indiquer le nombre d'octets employés pour coder le caractère par une séquence de bits à 1 dans la partie des bits de poids fort du premier octet. La fin de la séquence de bits à 1 est marquée par un bit à 0. Les bits restant servent à coder les bits de poids fort du point de code du caractère.

  • Un bit de poids fort à 0 indique un codage sur un octet, pour les caractères ASCII de 0 à 127 codés sur les 7 bits restant.
  • Sinon, le nombre de bits à 1 indique le nombre total d'octets pour le caractère.
  • La séquence à un bit à 1 est réservée pour les octets supplémentaires de codage par groupe de 6 bits. Cela permet de repérer une position (adresse mémoire ou flux de lecture) située au milieu du codage d'un caractère.

Le tableau ci-dessous résume le codage UTF-8, où les lettres représentent les bits du point de code du caractère encodé.

Séquence de bits Points de code des caractères
0aaaaaaa U+000000-U+00007F
110aaaaa 10bbbbbb U+000080-U+0007FF
1110aaaa 10bbbbbb 10cccccc U+000800-U+00FFFF
11110aaa 10bbbbbb 10cccccc 10dddddd U+010000-U+10FFFF

Exemples

Exemples de codage UTF-8
Type Caractère Point de code
(hexadécimal)
Valeur scalaire Codage UTF-8
décimal binaire binaire hexadécimal
Contrôles [NUL] U+0000 00000000 0000000000
[US] U+001F 310011111 000111111F
Texte [SP] U+0020 320100000 0010000020
A U+0041 651000001 0100000141
~ U+007E 1261111110 011111107E
Contrôles [DEL] U+007F 1271111111 011111117F
Texte [NBSP] U+00A0 16000010 100000 11000010 10100000C2 A0
é U+00E923300011 101001 11000011 10101001C3 A9
߿ U+07FF204711111 111111 11011111 10111111DF BF
U+080020480000 100000 000000 11100000 10100000 10000000E0 A0 80
U+20AC8 3640010 000010 101100 11100010 10000010 10101100E2 82 AC
U+D7FF55 2951101 011111 111111 11101101 10011111 10111111ED 9F BF
Demi-codets U+D800(néant) (codage interdit)
U+DFFF
Usage privé [] U+E00057 3441110 000000 000000 11101110 10000000 10000000EE 80 80
[] U+F8FF63 7431111 100011 111111 11101111 10100011 10111111EF A3 BF
Texte U+F90063 7441111 100100 000000 11101111 10100100 10000000EF A4 80
U+FDCF64 9751111 110111 001111 11101111 10110111 10001111EF B7 8F
Non-caractères U+FDD064 9761111 110111 010000 11101111 10110111 10010000EF B7 90
U+FDEF65 0071111 110111 101111 11101111 10110111 10101111EF B7 AF

Variante : UTF-8 modifié

La variante « UTF-8 modifié » est un codage utilisé par Java basé sur UTF-8, mais codant les caractères au-delà de U+0x00FFFF sur 6 octets, c'est-à-dire 2 fois 3 octets pour les surrogates, car en Java le type caractère occupe 16 bits.

Séquence de bits Points de code des caractères
0aaaaaaa U+0000-U+007F
110aaaaa 10bbbbbb U+0080-U+07FF
1110aaaa 10bbbbbb 10cccccc U+0800-U+FFFF (incluant les paires U+D800-U+DBFF et U+DC00-U+DFFF)

De plus, le caractère nul (U+0000) est codé sur deux octets (C0 80), afin d'éviter l'octet nul, et de faciliter le repérage de fin de chaîne de caractère dans le code natif.

Variante : CESU-8

La variante CESU-8 est identique au « UTF-8 modifié » utilisé par Java, excepté le codage du caractère nul (U+0000).

UTF-16

UTF-16 est un codage Unicode où chaque caractère est codé sur une suite de un ou deux mots de 16 bits.

L'UTF-16 fait maintenant partie intégrante de la norme Unicode, qui dans son chapitre 3 Conformance la définit de façon très stricte.

L'UTF-16 n'est pas l'UCS-2 qui est le codage, plus simple, de chaque caractère sur deux octets. Ces deux normes sont pourtant appelées toutes les deux Unicode, car le codage est le même tant que l'on n'utilise pas les plages U+D800 à U+DFFF (en principe réservées) et les plages après U+FFFF (peu utilisées en occident).

L'UTF-16 est en particulier utilisé dans les environnements windows. Dans ce système, les API dites unicode utilisent ce standard. Il en va de même du système NTFS.

UTF-16 est le standard de chaînes de caractères utilisé par l'UEFI[1].

Description

Les points de code qui peuvent être représentés doivent être dans l’intervalle de validité U+0000 à U+10FFFF, et ne doivent pas être affectés à un non-caractère. Tous les caractères possibles dans Unicode possèdent de tels points de codes.

Tout point de code qui n’est pas un non-caractère, et dont la valeur peut être codée sur un seul codet de deux octets (16 bits), c’est-à-dire tout point de code U+0000 à U+D7FF et U+E000 à U+FFFD, est stocké sur un seul mot de 16 bits (la plage de non-caractères U+D800 à U+DFFF est donc exclue, c'est-à-dire les points de code dont les 5 bits de poids fort sont 11011).

Dans les autres cas, le caractère est un point de code d’un plan supplémentaire (donc entre U+10000 et U+10FFFD et dont les 16 bits de poids faible ne doivent pas égaler 0xFFFE ou 0xFFFF) ; il est alors stocké sur 2 mots (codets) successifs de 16 bits chacun, dont les valeurs correspondent aux points de codes réservés dans les demi-zones d’indirection allouées dans le plan multilingue de base des normes Unicode et ISO/CEI 10646 :

  • le premier mot aura les 6 bits de poids fort égaux à 110110 et sera donc compris dans l’intervalle [0xD800 .. 0xDBFF] (ici en numération hexadécimale) ; ce mot contiendra dans ses 10 bits de poids faible les 10 bits de poids fort de la différence (représentée sur 20 bits) entre le point de code à stocker et le premier point de code supplémentaire U+10000 ;
  • le second mot aura les 6 bits de poids fort égaux à 110111 et sera donc compris dans l’intervalle [0xDC00 .. 0xDFFF] (ici en numération hexadécimale) ; ce mot contiendra dans ses 10 bits de poids faible les 10 bits de poids faible du point de code à stocker.

Puis suivant le format de stockage des mots de 16 bits dans un flux ordonné d’octets, deux systèmes sont possibles pour le codage final :

Principe du codage UTF-16 en big endian (on représente ici les bits)
Numéro du caractère 00000000 000uuuuu xxxxxxyy yyyyyyyy
Codage UTF-16BE
(sur 2 octets)
  xxxxxxyy yyyyyyyy
(seulement si uuuuu = 00000)
Codage UTF-16BE
(sur 4 octets)
110110ww wwxxxxxx 110111yy yyyyyyyy
avec wwww = uuuuu - 1 (si uuuuu > 00000)
Principe du codage UTF-16 en little endian (on représente ici les bits)
Numéro du caractère 00000000 000uuuuu xxxxxxyy yyyyyyyy
Codage UTF-16LE
(sur 2 octets)
  yyyyyyyy xxxxxxyy
(seulement si uuuuu = 00000)
Codage UTF-16LE
(sur 4 octets)
wwxxxxxx 110110ww yyyyyyyy 110111yy
avec wwww = uuuuu - 1 (si uuuuu > 00000)

L’indication du type de codage utilisé (ordre des octets) peut être implicite pour le protocole utilisé, ou précisé explicitement par ce protocole (en indiquant par exemple les noms réservés "UTF-16BE" ou "UTF-16LE" dans un entête de charset MIME). Si le protocole ne permet pas de spécifier l’ordre des octets, et s’il permet l’une ou l’autre des alternatives, on pourra utiliser le codage UTF-16 du point de code valide U+FEFF comme indicateur en tête du flux de données (car un changement d’ordre de ses octets à la lecture du flux conduira à un point de code U+FFFE, valide dans Unicode mais affecté à un non-caractère et donc interdit dans ce cas dans tout flux UTF-16. Ce point de code ainsi représenté (appelé marque d’ordonnancement des octets, byte order mark en anglais, abrégé BOM) ne sera codé qu’au début du flux de données, et permet de savoir comment a été codé le flux :

1er octet2ème octetCodage effectif
0xFE0xFFbig endian
0xFF0xFElittle endian

Si l’une des deux séquences de deux octets chacune est présente en tête de flux, le type de codage en est déduit et la séquence est retirée du flux : elle ne représente aucun caractère du texte stocké dans ce flux de données. Si aucune des deux séquences ne figure en tête du flux de données, la norme Unicode spécifie que le flux doit être décodé en big endian (UTF-16BE).

Le BOM peut également être présent en UTF-8 pour indiquer explicitement le codage.

Références

  1. http://x86asm.net/articles/uefi-programming-first-steps/
Cet article est issu de Wikibooks. Le texte est sous licence Creative Commons – Attribution – Partage à l’identique. Des conditions supplémentaires peuvent s’appliquer aux fichiers multimédias.