UTF-8 est un moyen relativement simple de coder les points de code Unicode dans un format à largeur variable de sorte qu'il ne confond pas facilement le code qui n'est pas compatible avec Unicode.
Présentation de l'UTF-8
- Les octets compris entre 1 et 0 x 7 F, inclus, sont normalement valides
- Les octets avec la configuration binaire
10XX XXXX
sont considérés comme des octets de continuation, les six bits les moins significatifs étant utilisés pour coder une partie d'un point de code. Ceux-ci ne doivent apparaître que s'ils sont attendus par un octet précédent. - Les octets avec le modèle
110X XXXX
attendent un octet de suite par la suite - Les octets avec le modèle
1110 XXXX
attendent deux octets de suite par la suite - Les octets avec le modèle
1111 0XXX
attendent trois octets de suite par la suite - Tous les autres octets ne sont pas valides et ne doivent apparaître nulle part dans un flux UTF-8. Les clusters de 5, 6 et 7 octets sont théoriquement possibles, mais ne seront pas autorisés aux fins de ce défi.
Encodages trop longs
UTF-8 exige également qu'un point de code soit représenté avec le nombre minimal d'octets. Toute séquence d'octets pouvant être représentée avec moins d'octets n'est pas valide. UTF-8 modifié ajoute une exception à cela pour les caractères nuls (U + 0000), qui devraient être représentés comme C0 80
(représentation hexadécimale)), et interdit à la place les octets nuls à apparaître n'importe où dans le flux. (Cela le rend compatible avec les chaînes terminées par null)
Défi
Vous devez créer un programme qui, lorsqu'il recevra une chaîne d'octets, déterminera si cette chaîne représente un UTF-8 modifié valide et renverra une valeur véridique si elle est valide et une valeur falsifiée dans le cas contraire. Notez que vous devez vérifier les encodages trop longs et les octets nuls (car il s'agit de UTF-8 modifié). Vous n'avez pas besoin de décoder les valeurs UTF-8.
Exemples
41 42 43 ==> yes (all bytes are in the 0-0x7F range)
00 01 02 ==> no (there is a null byte in the stream)
80 7F 41 ==> no (there is a continuation byte without a starter byte)
D9 84 10 ==> yes (the correct number of continuation bytes follow a starter byte)
F0 81 82 41 ==> no (there are not enough continuation bytes after F0)
EF 8A A7 91 ==> no (too many continuation bytes)
E1 E1 01 ==> no (starter byte where a continuation byte is expected)
E0 80 87 ==> no (overlong encoding)
41 C0 80 ==> yes (null byte encoded with the only legal overlong encoding)
F8 42 43 ==> no (invalid byte 'F8')
Règles
- Des règles et des lacunes standard s'appliquent
- L'entrée et la sortie peuvent être dans n'importe quel format pratique tant que toutes les valeurs dans la plage d'octets non signés (0-255) peuvent être lues.
- Vous devrez peut-être utiliser un tableau ou un fichier plutôt qu'une chaîne terminée par un caractère nul. Vous devez pouvoir lire des octets nuls.
- Le code le plus court gagne!
- Notez que l'utilisation de fonctions intégrées pour décoder l'UTF-8 n'est pas garantie de se conformer aux exigences données ici. Vous devrez peut-être contourner ce problème et créer des cas spéciaux.
EDIT: bonus supplémentaire pour ne pas utiliser de builtins qui décodent UTF-8
EDIT2: bonus supprimé car seule la réponse Rust est qualifiée et difficile à définir.