Convertisseur UTF-8 vers Unicode pour un affichage système intégré

J’ai un système intégré qui permet d’afficher des données codées UTF-8 via UPNP. Le dispositif d’affichage peut afficher des caractères. J’ai besoin d’un moyen de convertir les données UTF-8 que je reçois via UPNP en Unicode. L’affichage est sur un PIC et les données sont envoyées via un pont UPNP sous Linux. Existe-t-il un moyen simple d’effectuer la conversion avant de l’envoyer au tableau d’affichage sous Linux?

Si vous disposez d’un système d’exploitation réel et d’un environnement C hébergé, la meilleure approche consiste simplement à vous assurer que votre programme s’exécute dans une langue utilisant l’encodage UTF-8 et d’utiliser mbrtowc ou mbtowc pour convertir les séquences UTF-8 en Valeurs de points de code Unicode ( wchar_t est un nombre de points de code Unicode sous Linux et toute implémentation C définissant __STDC_ISO_10646__ ).

Si vous souhaitez ignorer les routines de la bibliothèque système et effectuer le décodage UTF-8 vous-même, soyez prudent. Une fois, j’ai mené une enquête occasionnelle à l’aide de la recherche de code Google et découvert qu’entre 1/3 et 2/3 du code UTF-8 à l’état sauvage était dangereusement faux. Voici une implémentation tout à fait correcte, rapide et simple que je recommande vivement:

http://bjoern.hoehrmann.de/utf-8/decoder/dfa/

Mon implémentation dans musl est un peu plus petite en taille binary et semble être plus rapide, mais elle est aussi un peu plus difficile à comprendre.

Pour convertir un tableau d’octets codés au format UFT-8 en un tableau de points de code Unicode:

L’astuce consiste à détecter diverses erreurs d’encodage.

 #include  #include  #include  #include  typedef struct { uint32_t UnicodePoint; // Accumulated code point uint32_t Min; // Minimum acceptable codepoint int i; // Index of char/wchar_t remaining bool e; // Error flag } UTF_T; static bool IsSurrogate(unsigned c) { return (c >= 0xD800) && (c <= 0xDFFF); } // Return true if more bytes needed to complete codepoint static bool Put8(UTF_T *U, unsigned ch) { ch &= 0xFF; if (U->i == 0) { if (ch <= 0x7F) { U->UnicodePoint = ch; return false; /* No more needed */ } else if (ch <= 0xBF) { goto fail; } else if (ch <= 0xDF) { U->Min = 0x80; U->UnicodePoint = ch & 0x1F; U->i = 1; } else if (ch <= 0xEF) { U->Min = 0x800; U->UnicodePoint = ch & 0x0F; U->i = 2; } else if (ch <= 0xF7) { U->Min = 0x10000; U->UnicodePoint = ch & 0x07; U->i = 3; } else { goto fail; } return true; /* More needed */ } // If expected continuation character missing ... if ((ch & (~0x3F)) != 0x80) { goto fail; } U->UnicodePoint <<= 6; U->UnicodePoint |= (ch & 0x3F); // If last continuation character ... if (--(U->i) == 0) { // If codepoint out of range ... if ((U->UnicodePoint < U->Min) || (U->UnicodePoint > 0x10FFFF) || IsSurrogate(U->UnicodePoint)) { goto fail; } return false /* No more needed */; } return true; /* More needed */ fail: U->UnicodePoint = -1; U->i = 0; U->e = true; return false /* No more needed */; } /* return 0:OK, else error */ bool ConvertUTF8toUnicodeCodepoints(const char *UTF8, size_t Length, uint32_t *CodePoints, size_t *OutLen) { UTF_T U = { 0 }; *OutLen = 0; for (size_t i = 0; i < Length;) { while (Put8(&U, UTF8[i++])) { // Needed bytes not available? if (i >= Length) { return true; } } if (Ue) break; CodePoints[(*OutLen)++] = U.UnicodePoint; } return Ue; } 

Ceci est basé sur un ancien code, veuillez le signaler, car il se peut qu’il ne soit pas conforme aux normes actuelles.
Pas le plus joli avec goto et numéros magiques.

Ce qui est bien avec cette approche est plutôt que CodePoints[(*OutLen)++] = U.UnicodePoint pour consumr le sharepoint code, si on voulait extraire UTF16 (BE ou LE), on pourrait facilement écrire du code consommateur pour le bloc UTF_T et pas besoin de changer à la partie UTF8 -> codepoint.

J’utiliserais les fonctions de manipulation Unicode de GLib, une bibliothèque d’utilitaires sous licence LGPL. Cela ressemble à g_utf8_to_ucs4 () est ce que vous recherchez.