utf-8
Le
tth

Bonsoir.
Voilà, j'ai du vieux code bien cracra (20 ans d'age) à qui il arrive
de traiter du texte. Avec des casts de goret dedans. Et maintenant,
je voudrais que ce machin comprenne l'utf-8 de manière propre.
Voici donc deux questions :
- Où trouver un guide des bonnes pratiques dans ce domaine ?
- Vers quoi me tourner pour une conversion utf-8 -> CP437 ?
tTh, angoissé
--
http://my.smeuh.org/
Voilà, j'ai du vieux code bien cracra (20 ans d'age) à qui il arrive
de traiter du texte. Avec des casts de goret dedans. Et maintenant,
je voudrais que ce machin comprenne l'utf-8 de manière propre.
Voici donc deux questions :
- Où trouver un guide des bonnes pratiques dans ce domaine ?
- Vers quoi me tourner pour une conversion utf-8 -> CP437 ?
tTh, angoissé
--
http://my.smeuh.org/
À tout hasard, libiconv pourrait te convenir ? J'ai utilisé pour
ressusciter un vieux code (début des années 90) qui ne causait qu'ascii
pour lui faire comprendre les encodages modernes. C'est même visible en
ligne sur gougeule code[¹].
Meuh non, ça va bien se passer :o)
[¹] https://code.google.com/p/patrocle/source/browse/trunk/bot/
--
Sébastien Kirche
Les deux « classiques » du domaine sont iconv (et libiconv) et recode
(et librecode) :
https://www.gnu.org/software/libiconv/
https://github.com/pinard/Recode
Il y a également ICU d'IBM, beaucoup utilisé fin 90/début 2000 mais qui
me semble en perte de vitesse et qui est assez usine à gaz :
http://site.icu-project.org/
Pour de la lecture, il y a par exemple ceci :
http://www.cl.cam.ac.uk/~mgk25/unicode.html
http://unicodebook.readthedocs.org/ (non joignable pour le moment mais dans le cache Google)
http://www.joelonsoftware.com/articles/Unicode.html
http://unicode.org/faq/programming.html
http://linuxgazette.net/147/pfeiffer.html
--
DW
Oui, je regarde iconv(3) et je pense que c'est bon pour ce que
je veux faire. Mais ça ne répond pas à ma première question.
Des incertitudes àlc genre "que retourne strlen sur un argv[2]
qui vient d'un shell en utf8 ?" ce genre de chose qui peut
conduire à un *poke* dans la pile, voire même pire.
--
--- http://my.smeuh.org/ ---
strlen() et ses amis renverront toujours le nombre d'octets, mais pas nécessairement le nombre de caractères.
donc en utf-8,
strlen("e") == 1
strlen("é") == 2
strlen("ₑ") == 3
Du coup il n'est plus possible d'accéder en temps constant au Nième *caractère*, mais c'est toujours bon pour le Nième *octet* :)
Mais pas mal de propriétés restent vraies: l'ascii est préservé (tout l'ascii 7-bit), le tri fonctionne toujours (le tri standard d'une chaîne utf-8 va également trier selon le code unicode), etc.
Selon le programme, cela peut ou non être gênant (typiquement si on traite les arguments comme des chaines opaques pour open(), cela ne pose aucun souci)
UTF-8 est un encodage de caractères à longueur variable, ce qui est un
peu plus complexe que les encodages à longueur fixe (ASCII, iso-8859,
UTF-32, ou l'Unicode original UCS-2) ; mais en dehors de cela, c'est un
encodage très facile à manipuler: il n'est pas ambigu, il est
déterministe (pas d'état), il se resynchronise en 6 octets au maximum.
Tous les guides sur les encodages à longueur variable peuvent donc
convenir. Par exemple, ceux écrit par Apple, Microsoft ou IBM dans les
années 1980 (à l'époque du Shift-JIS).
Le nombre de "bytes" (multiplet en français du livre).
Ce qu'il faut comprendre avec les encodages à longueur variable, c'est
que les chaînes (char*) représentent une suite de caractères, et qu'il
faut les manipuler comme telles. En particulier, un caractère est une
chaîne (qui a entre 1 et 6 bytes, plus le ' ' final).
Autrement dit, les manipulations de str* ou de char* sont normalement
sans problème ; ce à quoi il faut s'intéresser, c'est aux manipulations
sur les caractères individuels. Surtout quand ce ne sont _pas_ des
chiffres ou des lettres du code US-ASCII.
même pire.
Uniquement avec des manipulations douteuses. Et avec UTF-8, c'est
difficile, parce qu'il faut avoir de mauvaises intentions pour se
tromper à ce point. Par exemple, un truc horrible du genre
for (char*p; *p; p++) {
/* . . . */
if (*p == 'è') *p ='e'; // supprime les accents
va peut-être susciter un avertissement du compilateur (parce que 'è' est
une constante caractère multi-byte, un truc louche et pas portable) mais
à par cela, il n'y aura pas d'effet (et le è va garder son accent).
Pour moi, la conséquence la plus visible de l'UTF-8, c'est que les
déclarations de chaînes doivent être agrandies.
Antoine
Attention aux buffer overflow. Il y a eu des tonnes de bug dans la
plupart des bibliotheques de gestion d'UTF8. Il ne faut *pas* faire
confiance aveuglement a une chaine "en instance de decodage" mais bien
bloquer a 6 octets, meme si on ne voit pas d'octet de fin.
Une autre difficulte d'utf8 est liee aux diacritiques (les accents): il y a
plusieurs facons d'encoder le meme caractere + accent, et il faut se
renseigner sur les formes normales. C'est necessaire pour faire des
recherches de texte qui ressemblent a quelques choses.
Le dernier ecueil est purement fonctionnel: il y a des caracteres dont
la graphie est tres proche qui sont fondamentalement differents. C'est un
vecteur d'attaque pour les sites web internationaux (depuis qu'on peut
mettre de l'unicode dans les noms de site): l'analogue de se faire passer
pour microsoft en s'appelant micro$oft, mais en plus subtil et de facon
invisible avec une police usuelle...
Tous les navigateurs modernes decents ont un mecanisme ou deux pour empecher
ce genre de choses, en mettant dans une couleur differente un caractere
"louche" au milieu d'un nom de site.
Oui, bien sûr.
Ce qui me fait penser à un autre problème de UTF-8 (qui a été beaucoup
«exploité»), qui sont les faux encodages : exemple (utilisé par Java),
"xC0x80" «représente» la même chose que "