UTF-8 è un modo relativamente semplice per codificare i punti di codice Unicode in un formato a larghezza variabile in modo tale da non confondere facilmente il codice che non è a conoscenza di Unicode.
Panoramica UTF-8
- I byte nell'intervallo 1-0x7F, inclusi, sono normalmente validi
- I byte con il modello di bit
10XX XXXXsono considerati byte di continuazione, con i sei bit meno significativi utilizzati per codificare parte di un punto di codice. Questi non devono apparire a meno che non siano previsti da un byte precedente. - I byte con il modello
110X XXXXprevedono in seguito un byte di continuazione - I byte con il modello
1110 XXXXprevedono in seguito due byte di continuazione - I byte con il modello
1111 0XXXprevedono in seguito tre byte di continuazione - Tutti gli altri byte non sono validi e non dovrebbero apparire in nessun punto di un flusso UTF-8. I cluster a 5, 6 e 7 byte sono possibili in teoria, ma non saranno consentiti ai fini di questa sfida.
Codifiche troppo lunghe
UTF-8 richiede inoltre che un punto di codice sia rappresentato con il numero minimo di byte. Qualsiasi sequenza di byte che potrebbe essere rappresentata con meno byte non è valida. L'UTF-8 modificato aggiunge un'eccezione a questo per i caratteri null (U + 0000), che dovrebbero essere rappresentati come C0 80(rappresentazione esadecimale)) e non consente invece che i byte null vengano visualizzati in qualsiasi punto dello stream. (Questo lo rende compatibile con stringhe con terminazione null)
Sfida
Devi creare un programma che, quando viene data una stringa di byte, determinerà se quella stringa rappresenta UTF-8 modificato valido e restituirà un valore di verità se valido e un valore di falsa in caso contrario. Si noti che è necessario verificare la presenza di codifiche troppo lunghe e byte null (poiché si tratta di UTF-8 modificato). Non è necessario decodificare i valori UTF-8.
Esempi
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')
Regole
- Si applicano regole standard e scappatoie
- L'input e l'output possono essere in qualsiasi formato conveniente purché tutti i valori nell'intervallo di byte senza segno (0-255) possano essere letti.
- Potrebbe essere necessario utilizzare un array o un file anziché una stringa con terminazione null. Devi essere in grado di leggere byte null.
- Vince il codice più corto!
- Si noti che l'uso di builtin per decodificare l'UTF-8 non è garantito conforme ai requisiti indicati qui. Potrebbe essere necessario aggirarlo e creare casi speciali.
EDIT: aggiunto il bonus per non usare i builtin che decodificano UTF-8
EDIT2: bonus rimosso poiché solo la risposta Rust è qualificata ed è difficile da definire.