C: Le moyen le plus efficace de déterminer le nombre d’octets nécessaires pour une chaîne UTF-16 à partir d’une chaîne UTF-8

J’ai vu un code très intelligent pour la conversion entre les points de code Unicode et UTF-8, donc je me demandais si quelqu’un l’aurait (ou aimerait le concevoir).

  • Avec une chaîne UTF-8, combien d’octets sont nécessaires pour le codage UTF-16 de la même chaîne.
  • Supposons que la chaîne UTF-8 a déjà été validée. Il n’a pas de nomenclature, pas de séquence trop longue, pas de séquence invalide, est terminé par zéro. Ce n’est pas CESU-8 .
  • Le format UTF-16 complet avec des substituts doit être pris en charge.

Plus précisément, je me demande s’il existe des raccourcis pour savoir quand une paire de substitution sera nécessaire sans convertir complètement la séquence UTF-8 en un sharepoint code.

Le meilleur code UTF-8 à codepoint que j’ai vu utilise des techniques de vectorisation, je me demande donc si c’est également possible ici.

L’efficacité est toujours un compromis vitesse / taille. Si la vitesse est privilégiée par rapport à la taille, la méthode la plus efficace consiste simplement à deviner en fonction de la longueur de la chaîne source.

Il y a 4 cas à prendre en compte, prenons simplement le pire des cas comme taille finale de la mémoire tampon:

  • U + 0000-U + 007F – encodera 1 octet en utf8 et 2 octets par caractère en utf16. (1: 2 = x2)
  • U + 0080-U + 07FF – codé en séquences utf8 de 2 octets ou en caractères utf16 de 2 octets par caractère. (2: 2 = x1)
  • U + 0800-U + FFFF – sont stockés sous forme de séquences utf8 de 3 octets, mais peuvent néanmoins contenir des caractères utf16 simples. (3: 2 = x.67)
  • U + 10000-U + 10FFFF – sont stockés sous forme de séquences utf8 de 4 octets ou de paires de substitution dans utf16. (4: 4 = x1)

Le facteur d’expansion le plus défavorable concerne la traduction de U + 0000-U + 007f d’utf8 à utf16: le tampon, octet par seconde, doit simplement être deux fois plus grand que la chaîne source. Chaque autre sharepoint code unicode donne une taille égale ou une allocation plus petite octet par octet lorsqu’il est codé en tant que utf16 en tant que utf8.

Très simple: compter le nombre d’octets de tête, compter le double d’octets F0 et plus.

Dans du code:

 size_t count(unsigned char *s) { size_t l; for (l=0; *s; s++) l+=(*s-0x80U>=0x40)+(*s>=0xf0); return l; } 

Remarque: Cette fonction renvoie la longueur en unités de code UTF-16. Si vous souhaitez connaître le nombre d’octets nécessaires, multipliez ce nombre par 2. Si vous souhaitez stocker un terminateur nul, vous devez également prendre en compte l’espace disponible (une unité de code supplémentaire / deux octets supplémentaires).

Ce n’est pas un algorithme, mais si je comprends bien, les règles sont comme telles:

  • chaque octet ayant un MSB de 0 ajoute 2 octets (1 unité de code UTF-16)
    • cet octet représente un seul sharepoint code Unicode dans la plage U + 0000 – U + 007F
  • chaque octet ayant les MSB 110 ou 1110 ajoute 2 octets (1 unité de code UTF-16)
    • ces octets commencent par des séquences de 2 et 3 octets représentant respectivement les points de code Unicode dans la plage U + 0080 – U + FFFF
  • chaque octet ayant le jeu de 4 MSB (c’est-à-dire à partir de 1111 ) ajoute 4 octets (2 unités de code UTF-16)
    • ces octets commencent par des séquences de 4 octets qui couvrent “le rest” de la plage Unicode, ce qui peut être représenté avec un substitut haut et bas dans le format UTF-16
  • chaque autre octet (c’est-à-dire ceux commençant par 10 ) peut être sauté
    • ces octets sont déjà comptés avec les autres.

Je ne suis pas un expert en C, mais cela semble facilement vectorisable.