J'écris une couche wrapper à utiliser avec mingw qui fournit à l'application un environnement virtuel UTF-8. Les fonctions qui traitent des noms de fichiers sont des wrappers qui convertissent à partir de UTF-8 et appellent les fonctions "_w" correspondantes, et ainsi de suite. Le gros problème que j'ai rencontré est que Windows 'wchar_t
est 16 bits.Comment traiter au mieux la laideur de wchar_t 16 bits de Windows?
Pour les opérations de système de fichiers, ce n'est pas grave. Je peux juste convertir d'avant en arrière entre UTF-8 et UTF-16, et tout va fonctionner. Mais l'API de conversion de caractères multi-octets/caractères C standard n'autorise pas les caractères multi-wchar_t.
solutions possibles:
- Fournir un environnement CESU-8 au lieu de UTF-8. Je n'aime vraiment pas celui-ci.
- Prenez la sortie facile et ne supporte que le BMP. Traiter les séquences UTF-8 de longueur 4 comme non valides.
- Extension de l'enveloppe pour remplacer
wchar_t
deet traiterWCHAR
etwchar_t
étant différent. C'est un problème, mais il peut être idéal pour le portage d'applications qui exigent un environnement propre de type POSIX et n'utilise paswchar_t
à des fins d'API Windows. - L'entaille suivante:
mbrtowc
délivre un wchar_t
correspondant à la porteuse haute après avoir lu les 3 premiers octets d'un caractère UTF-8 de 4 octets, et maintient l'état restant dans l'objet mbstate_t
. Lors de la réception de l'octet suivant, il le combine avec l'état enregistré pour sortir le substitut faible. Si le dernier octet finit par être invalide, il renvoie -1 (avec EILSEQ) et un seul substitut se retrouve dans le flux de sortie (mauvais ...).
wcrtomb
génère les 2 premiers octets de UTF-8 lorsqu'il traite le substitut haut, et enregistre l'état restant dans son objet mbstate_t
. Quand il traite ensuite le substitut bas, il combine cela avec l'état sauvegardé pour sortir les 2 derniers octets de UTF-8. Si un substitut bas valide n'est pas reçu, il renvoie -1 (avec EILSEQ) et une séquence UTF-8 incomplète finit dans le flux de sortie (mauvais ...). Le côté positif de ce hack est qu'il fonctionne tant que l'entrée est valide, et permet d'accéder à n'importe quel caractère UTF-8 et donc à tout nom de fichier/argument/etc. texte avec lequel l'application pourrait devoir travailler. Les inconvénients sont qu'il n'est pas strictement conforme à ISO C (wchar_t
chaîne n'est pas autorisé à être à état) et qu'il retarde la détection des caractères malformés jusqu'à ce que la sortie partielle incorrecte a déjà été écrite. Je suis à la recherche de commentaires sur les différentes options, et en particulier mon hack proposé: si c'est raisonnable, si les inconvénients sont susceptibles de causer des erreurs graves, et s'il y a d'autres inconvénients que je n'ai pas encore considérés qui pourraient empêcher le système de fonctionner entièrement. Je serais également heureux d'entendre toutes les autres solutions possibles auxquelles je n'avais pas pensé.
Cela semble bien, mais je ne suis pas sûr que ce soit possible. Si 'mbrtowc' stocke le substitut bas dans' mbstate_t', alors il devrait sortir un 'wchar_t' lors de l'appel suivant sans consommer d'entrée. Mais la valeur de retour de 0 est réservée à la conversion d'un octet/fin de chaîne nul. Je suppose qu'il pourrait consommer un octet supplémentaire du caractère suivant, mais s'il s'agissait d'un caractère à un octet, l'étrange tampon continuerait. Qu'est-ce que tu penses? –
C'est dur, car la norme C suppose que 'wchar_t' peut représenter n'importe quel caractère, et Microsoft l'a violé. Je ne pense pas qu'il soit possible d'écrire un 'mbrtowc 'conforme avec UTF-16. – dan04
La valeur de retour 0 peut ne pas poser de problème si le code appelant vérifie la valeur de 'wch' au lieu de supposer U + 0000 en fonction de la valeur de retour. Je n'utilise pas 'mbrtowc' moi-même (à la place, une fonction de conversion développée en interne qui fonctionne sur des chaînes entières), donc je ne suis pas sûr de la quantité de problèmes que cela poserait en pratique. – dan04