Re: Jeux de caractères, notamment UT F-8

Thomas De Contes <[email protected]> Tue, 8 Dec 2020 01:22:24 +0100
Newsgroups gmane.comp.lang.ada.france
Message-ID <[email protected]>
Le 9 sept. 2020 à 11:36, Pascal Pignard a écrit :

> Le 8 sept. 2020 à 19:34, Thomas De Contes <[email protected]> a écrit :

>> 1
>> quand je faisais des sites web, à un moment donné je me suis penché sur la question du "meilleur" jeu de caractères à utiliser

> Latin 1 est celui retenu par Ada pour le type Character et donc String.

ça me parait parfaitement logique, String / Wide_String / Wide_Wide_String étant construits dans la continuité, et alignés sur Unicode "brut" sans aucun encodage

> UTF-8 est plus utilisé aujourd'hui pour Internet bien que Windows et macOS utilise UTF-16.

(pour moi ce qui serais le plus logique c'est qu'on mette UTF-8 partout,
dans quels cas UTF-16 est il mieux ?)

> Gnoga (https://sourceforge.net/p/gnoga/) par exemple utilise le Latin 1 pour tout ce qui est Ada et UTF-8 pour tout ce qui est Web / Javascript.

je ne comprend pas très bien :
comment faites vous vos littéraux par exemple ? ils sont dans le code ada mais destinés aux interfaces ...


> 
>> 2
>> utilisation de gnat
>> 
>> j'ai un peu de mal à comprendre comment ça marche :
>> https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gnat_ugn/Character-Set-Control.html
>> 
>> par exemple, si je met les options "-gnati5 -gnatWs",
>> concrètement, comment gnat va t il lire mon code ?
>> avec Cyrillic pour les identifiants et Shift/JIS pour les littéraux de chaines de caractères ?
>> et si j'ai bien compris, dans les commentaires, tous les caractères non-ASCII sont autorisés tout le temps (sauf NEL) ?
>> 
>> (y a t il autre chose que identifiants / littéraux / commentaires, où on écrit potentiellement comme on veut ?)
> 
> Voir l'article sur les accentuations :
> https://blady.pagesperso-orange.fr/a_savoir.html#accents

merci :-)
(souhaites tu que je te rapportes les coquilles, ou c'est un document fait une fois pour toutes auquel tu ne touches plus ?)

ça me confirme ce que j'ai cru comprendre en lisant la doc (en gros le point 3), et que le mainteneur de rapid a eu raison de me remonter les bretelles quand j'ai fait comme dans l'exemple à ne pas faire ;-)

mais ça ne répond pas complètement à cette question (point 2), puisque ça ne parle pas de -gnati


> 
>> 3
>> ce que je crois avoir compris, par contre, c'est comment ada et gnat envisagent UTF-8 :
>> 
>> 
>> les auteurs ont déjà fait plusieurs pas en direction d'unicode et UTF-8, notamment avec le paquetage Ada.Strings.UTF_Encoding (A.4.11), mais ne sont pas encore arrivés au bout


>> du coup, si on veut bénéficier du potentiel d'unicode, avec la possibilité d'utiliser n'importe quel caractère, sans avoir besoin de revenir sur aucun réglage le jour où l'envie nous prend (ou le besoin survient),
>> on doit utiliser l'option -gnatW8 combinée avec Standard.Wide_Wide_String
>> 
>> ce qui implique :
>> 
>> - quand on n'utilise que de l'ASCII (l'immense majorité du temps) ça prend 4 fois plus de mémoire que nécessaire
>> 
>> - ça dois faire 2 conversions inutiles (puisqu'elles sont symétriques) :
>> - le compilateur doit convertir l'UTF-8 en Wide_Wide_String
>> - le programme doit convertir le Wide_Wide_String en UTF-8, avec Ada.Strings.UTF_Encoding.Wide_Wide_Strings.Encode, pour pouvoir le passer à GtkAda
> 
> Essaye d'utiliser Pango comme fait dans Gnoga.

merci pour l'astuce :-)
peux tu me guider stp ?

j'ai trouvé le code source ici :
https://sourceforge.net/p/gnoga/code/ci/dev_1.5/tree/src/

mais, dans quels fichiers faut il regarder pour trouver comment il utilise Pango ?



> 
>> 4
>> l'idéal, ça serais de pouvoir écrire un programme en UTF-8, y compris des littéraux de chaines de caractères, et que ça soit interprété directement sous la forme Ada.Strings.UTF_Encoding.UTF_8_String, sans aucune conversion
>> (par exemple pour qu'on puisse le passer directement à GtkAda)
>> 
>> - est ce que dans les révisions futures, notamment la prochaine, vous continuez à vous rapprocher de ça ?
>> 
>> - y a t il un moyen de faire ça proprement des aujourd'hui ?
>> (idéalement quelque chose qui pourrais être accepté dans le code de gnat lui-même :-) bon là je crois que je rêve ;-) )
> 
> Que penses-tu de la proposition UXString:
> https://sourceforge.net/p/gnoga/code/ci/dev_1.6/tree/deps/uxstrings/


bon, tu me poses la question "Qu'en penses-tu" et moi j'ai bien envie d'y répondre ;-)
alors pour découper ma réponse, pour la rendre plus lisible (j'espère), je recommence une numérotation (sans lien avec la précédente)


je trouve que cette proposition n'est pas parfaitement appropriée en l'état, d'après mes connaissances sur Ada et autour,
mais il y a plein de choses intéressantes :-)


(mais au fait, est ce que c'est pour l'instant seulement une proposition pour une amélioration future du langage, ou est ce que c'est quelque chose qui pourrais déjà marcher avec Ada 2012, des que l'implémentation sera terminée, avec par exemple les "aspects", que je ne maitrise pas encore ?)

(j'ai écrit le point 1 avant de voir le début d'implémentation, au point 5,
je croyais que tu proposais quelque chose d'"assez statique", pleinement intégré au langage, géré automatiquement par le compilateur (en quelques sortes en remplacement de UTF_8_String avec toutes les mêmes fonctionnalités que String),
du coup je suis peut-être un peu à coté de la plaque - tant pis, je le laisse quand même)


1
en fait, ce que tu proposes me semble ressembler plus à ce que fait Caml avec les pointeurs, c'est à dire qu'il les gère automatiquement pour que le programmeur n'ait pas à s'en occuper

alors en fait, à l'origine j'aurais préféré qu'Ada gère les pointeurs comme Caml, puisque je ne fais que de simples applications, je n'ai jamais besoin d'aller dans le détail (jusqu'à maintenant), donc ça aurais été plus sécurisant

mais puisque programmer dans le détail est un avantage d'Ada, il faut le garder ! et je ne sais pas si ta proposition est suffisamment compatible pour être acceptée

je pense qu'au moins il faudrait que tu précises avec suffisamment de détails ce que tu attends comme comportement pour la gestion interne dans certains cas :
- si on a une variable UXString dont la représentation interne utilise un jeu de caractères restreint (Latin-1 ou BMP), et si on ajoute (par insertion, substitution, concaténation, ...) un caractère sortant du jeu de caractères courant, comment le programme est il censé gérer cette situation ?
- si à l'inverse, on supprime le dernier caractère d'un jeu de caractères "étendu", de sorte que le nouveau jeu de caractères optimal devient plus petit que le jeu de caractères courant ? est ce qu'on doit immédiatement tout reconvertir dans l'implémentation du jeu de caractères optimal, ou est ce qu'on attend un peu de voir si ça dure ou pas, par exemple ?


2
je trouve très intéressante l'énumération des 3 possibilités que t'as faite vers le début :-)

- la 3ème, que t'as choisie, j'espère avoir correctement expliqué pourquoi ça n'est pas ma préférée

- la 2ème, comme je l'écris à Jean-Pierre, ben je trouve qu'un compromis qui fait qu'à la fois on gaspille un peu de mémoire et on n'a pas accès à tous les caractères, quand on a la possibilité de faire mieux, c'est un mauvais compromis
(mais je crois que tu es d'accord)

- la 1ère reste pour l'instant ma préférée,

mais c'est du au fait que j'ai une quantité de petits littéraux parsemés tout au long du code, dont je ne fais rien d'autre que de les passer à GtkAda,
donc dans ces cas là, en général on n'a pas la nécessité de compter le nombre de caractères,
il me semble qu'à part les concaténations, on fait très peu d'opérations sur les chaines, découpages, etc. (et il me semble que GtkAda n'en fait pas plus en interne, mais je peux me tromper)

donc ce qui me parait le plus simple c'est que tout ça soit de l'UTF-8 et que le compilateur le sache, simplement, et qu'il n'y ait aucune conversion nulle part
(gestion native de l'UTF-8 par le compilateur de bout en bout)

par contre, si je te lis bien, il y a au moins un cas de figure, avec certaines taches liées à Javascript, dans lequel t'as beaucoup plus d'opérations à faire sur les chaines, incluant des index et des longueurs,
donc merci de m'avoir rappelé que UTF_8_String pose des problèmes dans ce cas là, puisqu'on s'attend à faire les calculs sur des caractères alors que là ça les fait sur des octets, ça avait échappé à ma réflexion jusqu'à ce moment :-)


3
quand tu dis "Some combinations may lead to incorrect UTF-8 representation.", peux tu préciser ?

quand on découpe une chaine d'octets au milieu, à condition d'être sur que c'était une chaine UTF-8 bien formée au départ, c'est extrêmement simple de savoir si on a découpé entre 2 caractères ou au milieu d'un caractère :
il suffit de tester si l'octet suivant commence par 2#10# (est ce une bonne façon d'écrire, pour designer les 2 1ers bits de l'octet ?)

pour ce qui est des index et des longueurs, effectivement il faut parcourir la chaine, mais il suffit de compter tous les 2#0# et 2#11#, et d'ignorer les 2#10#, c'est quand même très peu gourmand en ressources par rapport à calculer les points de code ...
est ce que ça te parait quand même rédhibitoire ?


4
ce que tu proposes implique quand même pas mal de conversions (si c'était un type unique qui devait servir à tout),
et sauf erreur, et bien sur avec une bonne optimisation, une conversion entre Wide_Wide_String et UTF-8 est quand même significativement plus couteuse qu'un calcul d'index ou de longueur

alors peut-être que ce qu'il faudrait, c'est avoir les 2 :

- avoir des variables codées en UTF-8, qui sachent gérer les index et longueurs etc, pour qu'il n'y ait aucun risque pour le programmeur et aucune précaution nécessaire de sa part, en cas de besoins ponctuels

- avoir ta proposition UXString à coté,
avec largeur adaptative, mais constante sur toute la chaine à un instant donné,
pour pouvoir basculer dessus quand on pressent qu'on va avoir une quantité suffisante de traitements à faire dessus entre 2 conversions

qu'en penses tu ?
est ce prendre un marteau pilon pour écraser une mouche, que de proposer d'avoir les 2 mécanismes au choix ?


5
https://sourceforge.net/p/gnoga/code/ci/dev_1.6/tree/deps/uxstrings/src/uxstrings.ads


l 23-24

il me semble qu'au lieu de
   subtype UTF_8_Character is Character;
tu devrais plutôt écrire
   subtype UTF_8_Byte is Character;
(on a tout à gagner à bien nommer les choses des le début)

(pour UTF_16_Character je pense qu'il faudrait trouver un mot qui désigne un "double octet", mais je ne sais pas quel mot employer ni en français ni en anglais)


comme j'avais commencé à écrire ça avec ta version du 2020-09-12, je me suis aperçu que t'as changé
   type UTF_8_Character is new Character;
en
   subtype UTF_8_Character is Character;
pourquoi ?

et si à la place tu faisais quelque chose du genre
   type UTF_8_Byte is new Ada.Streams.Stream_Element;
quel genre de problèmes ça poserais ?


l 26-28, 84-87

je ne comprend pas ce mélange entre UTF_16BE / UTF_16LE et Wide_Character :
dans Ada.Strings.UTF_Encoding, ça utilise Encoding_Scheme avec UTF_String, mais pas avec UTF_16_Wide_String, ça n'en a pas besoin ...
l'envisages tu autrement ?


moins important, mais ça l'est quand même si on considère que ça pourrais être pleinement intégré au langage, et pas juste une bibliothèque additionnelle :

à chaque fois qu'on convertit dans un jeu de caractères restreint, tu nous imposes de choisir un caractère de substitution, pour les caractères se trouvant en dehors du jeu de caractères de destination :

je n'aime pas cette idée, j'aime beaucoup mieux que ça renvoie simplement une erreur, comme Ada.Strings.UTF_Encoding.Strings.Decode qui renvoie Encoding_Error
(au minimum il faudrait qu'on ait le choix)

le programmeur peut utiliser à loisir le type Ada.Strings.Wide_Wide_Maps.Wide_Wide_Character_Mapping pour transformer la variable en sorte qu'elle rentre dans le jeu de caractères souhaité



-- 
Téléassistance / Télémaintenance
http://invites.biocer.fr/thomas-de-contes/

_______________________________________________
Ada-france mailing list
[email protected]
https://mail.ada-france.org/cgi-bin/mailman/listinfo/ada-france