Celem jest stworzenie w pełni zgodnego konwertera między oficjalnymi kodowaniami Unicode, jak podano w FAQ UTF . Biorąc pod uwagę, że jest on wyśrodkowany na Unicode, zaakceptuję odpowiedź o najniższej liczbie bajtów przy użyciu najlepszego możliwego kodowania (prawdopodobnie będzie to UTF-8, chyba że programujesz go w APL). Przepraszam za długi post, ale wiele z nich wyjaśnia kodowania, do których można również uzyskać dostęp w oficjalnej specyfikacji (pdf, sekcja 3.9 D90 - D92) lub Wikipedia .
Dane techniczne
Jeśli w dowolnym momencie twój wybrany język nie może dokładnie spełnić wymagań, zastąp go czymś, co trzyma się ducha podanych zasad. Na przykład. nie każdy język ma wbudowane tablice, funkcje itp.
Brak korzystania z bibliotek / funkcji ciągów lub bibliotek / funkcji kodowania. Celem tego kodu golfa jest implementacja konwertera za pomocą manipulacji bitami / bajtami. Dozwolone jest jednak używanie samych łańcuchów jako tablicy znaków lub bajtów. Aha, i żadnych wywołań systemu operacyjnego, które wykonałyby konwersję.
Konwerter jest funkcją, która przyjmie trzy parametry: tablicę bajtów reprezentującą zakodowany ciąg wejściowy oraz kodowania „wejściowe” i „wyjściowe” przedstawione w postaci liczb. Arbitralnie przypiszemy
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
liczby od 0 do 6 w tej kolejności. Nie ma potrzeby sprawdzania, czy liczba jest równa< 0
lub> 6
, zakładamy, że parametry te są prawidłowe. Konwerter zwróci prawidłową tablicę bajtów w żądanym kodowaniu wyjściowym.Użyjemy znaku null (
U+0000
) jako terminatora łańcucha. Wszystko po tym nie ma znaczenia. Zakładamy, że tablica wejściowa ma gdzieś znak zerowy, więc nie trzeba sprawdzać granic.Zgodnie z często zadawanymi pytaniami , jeśli tablica bajtów wejściowych jest nieprawidłowa dla zadeklarowanego kodowania, musimy zasygnalizować błąd. Zrobimy to w jeden z następujących sposobów: zawiesimy program, wyrzucimy wyjątek, zwrócimy null lub zwrócimy tablicę, której pierwsze cztery bajty mają wartość 0 (aby można było ją rozpoznać jak
U+0000
w każdym kodowaniu).
Kodowania
Należy przestrzegać oficjalnych specyfikacji, ale Wikipedia zapewnia dobre (i, o ile uważam, poprawne) wyjaśnienie kodowania, i streszczę je tutaj dla kompletności. Zauważ, że UTF-16 i UTF-32 mają warianty endianizmu .
UTF-32, UTF-32LE, UTF-32BE
Najprostsze kodowanie, każdy punkt kodowy jest po prostu zakodowany w 4 bajtach równych jego wartości liczbowej. LE / BE oznacza endianness (little endian / big endian).
UTF-16, UTF-16LE, UTF-16BE
Punkty kodowe z U+0000 - U+FFFF
są zakodowane w 2 bajtach równych wartości liczbowej. Większe wartości są kodowane przy użyciu pary surogatów, które są zastrzeżonymi wartościami z U+D800 - U+DFFF
. Aby zakodować punkty większe niż U+FFFF
, można użyć następującego algorytmu (bezwstydnie skopiowanego z Wikipedii ):
- 0x010000 jest odejmowane od punktu kodowego, pozostawiając 20-bitową liczbę w zakresie 0..0x0FFFFF.
- Dziesięć górnych bitów (liczba w zakresie 0..0x03FF) dodaje się do 0xD800, aby dać pierwszą jednostkę kodu lub wiodące surogat, który będzie w zakresie 0xD800..0xDBFF [...].
- Dziesięć niskich bitów (również w zakresie 0..0x03FF) dodaje się do 0xDC00, aby dać drugą jednostkę kodu lub zastępczą ścieżkę, która będzie w zakresie 0xDC00..0xDFFF [...].
UTF-8
Punkty kodowe z U+0000 - U+007F
są kodowane jako 1 bajt równy wartości liczbowej. Od U+0080 - U+07FF
są one zakodowane jako 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
jest 1110xxxx 10xxxxxx 10xxxxxx
, wyższe wartości 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Thex
są bitami od wartości liczbowej punktu kodowego.
BOM
Znak kolejności bajtów (BOM, U+FEFF
) jest używany jako pierwszy punkt kodowy do wskazania endianizmu. Zgodnie z wytycznymi FAQ dotyczącymi BOM , BOM będzie używany w następujący sposób: UTF-8, UTF-16 and UTF-32
ponieważ jest opcjonalny. Jeśli BOM jest nieobecny w UTF-16
lub UTF-32
, zakłada się, że jest to duży endian. LM nie może pojawić się w UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Typowe pułapki powodujące nieprawidłowy UTF
Różne rzeczy mogą powodować, że sekwencja bajtów jest niepoprawna UTF.
- UTF-8 i UTF-32: Bezpośrednie kodowanie zastępczych punktów kodowych (
U+D800 - U+DFFF
) lub punktów kodowych większych niżU+10FFFF
. - UTF-8: Wiele nieprawidłowych sekwencji bajtów.
- UTF-16: Niesparowane lub niewłaściwie sparowane zastępcze.
- BOM: Należy użyć zgodnie z opisem w sekcji dotyczącej kodowania. Zauważ, że kiedy wypisujesz
UTF-16
lubUTF-32
(nie określono nieodłącznego endianizmu) możesz wybrać, ale z małym endianem ty musisz dołączyć BOM.
Zauważ, że niepoznakowe i nieprzypisane punkty kodowe (oba różne od zastępczych) należy traktować jak zwykłe znaki.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.