L'obiettivo è quello di creare un convertitore pienamente conforme tra le codifiche Unicode ufficiali come indicato in FAQ UTF . Dato che questo è incentrato su Unicode, accetterò la risposta con il conteggio di byte più basso usando la migliore codifica possibile (che probabilmente sarà UTF-8, a meno che non sia programmabile in APL). Mi scuso per il lungo post, ma molti spiegano le codifiche a cui è possibile accedere anche nelle specifiche ufficiali (pdf, sezione 3.9 D90 - D92) o Wikipedia .
specificazioni
Se in qualsiasi momento la tua lingua preferita non riesce a soddisfare esattamente un requisito, sostituiscilo con qualcosa che rispecchi lo spirito delle regole fornite. Per esempio. non tutte le lingue hanno matrici, funzioni integrate ecc.
Non utilizzare librerie / funzioni di stringa o codificare librerie / funzioni. Il punto di questo codice golf è implementare il convertitore usando la manipolazione bit / byte. L'uso delle stringhe stesse nella loro capacità è comunque consentito come carattere o array di byte. Oh, e nessuna chiamata del sistema operativo che esegue la conversione.
Il convertitore è una funzione che accetta tre parametri: un array di byte che rappresenta la stringa di input codificata e le codifiche "input" e "output" rappresentate come numeri. Arbitrariamente assegneremo i
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
numeri da 0 a 6 in questo ordine. Non è necessario verificare se il numero è< 0
o> 6
, assumeremo che questi parametri siano corretti. Il convertitore restituirà un array di byte valido nella codifica di output desiderata.Useremo il carattere null (
U+0000
) come terminatore di stringa. Nulla dopo questo non importa. Partiamo dal presupposto che l'array di input ha il carattere null da qualche parte, quindi non è necessario eseguire un controllo dei limiti.Come da FAQ , se l'array di byte di input non è valido per la sua codifica dichiarata, dobbiamo segnalare un errore. Lo faremo in uno dei seguenti modi: arresta il programma in modo anomalo, genera un'eccezione, restituisce null o restituisce un array i cui primi quattro byte sono tutti 0 (in modo che possa essere riconosciuto come
U+0000
in ogni codifica).
Le codifiche
Le specifiche ufficiali devono essere seguite, ma Wikipedia fornisce una buona (e per quanto ritengo corretta) spiegazione delle codifiche, e le riassumerò qui per completezza. Si noti che UTF-16 e UTF-32 hanno varianti per endianness .
UTF-32, UTF-32LE, UTF-32BE
La codifica più semplice, ogni punto di codice è semplicemente codificato in 4 byte pari al suo valore numerico. LE / BE rappresenta endianness (little endian / big endian).
UTF-16, UTF-16LE, UTF-16BE
I punti di codice da U+0000 - U+FFFF
sono codificati in 2 byte pari al suo valore numerico. I valori più grandi vengono codificati utilizzando una coppia di surrogati da cui sono riservati i valori U+D800 - U+DFFF
. Quindi, per codificare punti maggiori di U+FFFF
, è possibile utilizzare il seguente algoritmo (copiato senza vergogna da Wikipedia ):
- 0x010000 viene sottratto dal punto di codice, lasciando un numero di 20 bit nell'intervallo 0..0x0FFFFF.
- I primi dieci bit (un numero nell'intervallo 0..0x03FF) vengono aggiunti a 0xD800 per fornire la prima unità di codice o surrogato di derivazione, che sarà nell'intervallo 0xD800..0xDBFF [...].
- I dieci bit bassi (anche nell'intervallo 0..0x03FF) vengono aggiunti a 0xDC00 per fornire la seconda unità di codice o surrogato della traccia, che sarà nell'intervallo 0xDC00..0xDFFF [...].
UTF-8
I punti di codice da U+0000 - U+007F
sono codificati come 1 byte uguale al suo valore numerico. Da U+0080 - U+07FF
loro sono codificati come 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
è 1110xxxx 10xxxxxx 10xxxxxx
, sono valori più alti 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Le x
's sono i bit del valore numerico del punto di codice.
BOM
Il segno di ordine dei byte (DBA U+FEFF
) viene utilizzato come primo punto di codice per indicare l'endianità. Seguendo le linee guida delle FAQ sulle distinte base , la distinta base verrà utilizzata come segue: poiché UTF-8, UTF-16 and UTF-32
è facoltativa. Se la DBA è assente in UTF-16
o UTF-32
, si presume che sia big endian. La distinta componenti non deve apparire in UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Insidie comuni che causano UTF non valido
Varie cose possono causare una sequenza di byte non valida UTF.
- UTF-8 e UTF-32: codifica diretta di punti di codice surrogato (
U+D800 - U+DFFF
) o punti di codice maggiori diU+10FFFF
. - UTF-8: molte sequenze di byte non valide.
- UTF-16: surrogati non accoppiati o accoppiati in modo improprio.
- BOM: deve essere utilizzato come specificato nella sezione di codifica. Si noti che quando si emette
UTF-16
oUTF-32
(nessuna endianness intrinseca specificata) è possibile selezionare, ma con little endian, è necessario includere la distinta base.
Si noti che i punti di codice non caratteri e non assegnati (entrambi distinti dai surrogati) devono essere trattati come caratteri normali.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.