Mục tiêu là tạo ra một trình chuyển đổi tuân thủ đầy đủ giữa các bảng mã Unicode chính thức như được nêu trong Câu hỏi thường gặp về UTF . Vì đây là trung tâm của Unicode, tôi sẽ chấp nhận câu trả lời với số byte thấp nhất bằng cách sử dụng mã hóa tốt nhất có thể có (có lẽ sẽ là UTF-8, trừ khi bạn có thể lập trình nó trong APL). Tôi xin lỗi vì bài viết dài, nhưng rất nhiều trong số đó đang giải thích các bảng mã cũng có thể được truy cập trong thông số kỹ thuật chính thức (pdf, phần 3.9 D90 - D92) hoặc Wikipedia .
Thông số kỹ thuật
Nếu bất cứ lúc nào ngôn ngữ bạn chọn không thể đáp ứng chính xác một yêu cầu, hãy thay thế nó bằng thứ gì đó khắc phục tinh thần của các quy tắc được đưa ra. Ví dụ. không phải ngôn ngữ nào cũng có các mảng, hàm tích hợp, v.v.
Không sử dụng thư viện / hàm chuỗi hoặc mã hóa thư viện / hàm. Điểm của golf mã này là thực hiện trình chuyển đổi bằng cách sử dụng thao tác bit / byte. Mặc dù, việc sử dụng các chuỗi trong khả năng của họ như là một ký tự hoặc mảng byte được cho phép. Ồ, và không có cuộc gọi hệ điều hành nào thực hiện chuyển đổi.
Bộ chuyển đổi là một hàm sẽ có ba tham số: một mảng byte đại diện cho chuỗi đầu vào được mã hóa và mã hóa "đầu vào" và "đầu ra" được biểu diễn dưới dạng số. Tùy ý chúng tôi sẽ gán các
UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE, and UTF32LE
số từ 0 đến 6 theo thứ tự đó. Không cần phải kiểm tra xem số đó có phải< 0
hay không> 6
, chúng tôi sẽ cho rằng các tham số này là chính xác. Bộ chuyển đổi sẽ trả về một mảng byte hợp lệ trong mã hóa đầu ra mong muốn.Chúng ta sẽ sử dụng ký tự null (
U+0000
) làm dấu kết thúc chuỗi. Bất cứ điều gì sau đó không quan trọng. Chúng tôi sẽ giả định rằng mảng đầu vào có ký tự null ở đâu đó để bạn không cần thực hiện kiểm tra giới hạn.Theo Câu hỏi thường gặp , nếu mảng byte đầu vào không hợp lệ cho mã hóa được khai báo, chúng ta phải báo hiệu lỗi. Chúng tôi sẽ thực hiện điều này theo một trong các cách sau: đánh sập chương trình, ném ngoại lệ, trả về null hoặc trả về một mảng có bốn byte đầu tiên đều bằng 0 (để có thể nhận ra nó như
U+0000
trong mọi mã hóa).
Các bảng mã
Các thông số kỹ thuật chính thức phải được tuân theo, nhưng Wikipedia cung cấp một lời giải thích tốt (và theo như tôi tin là chính xác) về các mã hóa, và tôi sẽ tóm tắt chúng ở đây cho đầy đủ. Lưu ý rằng UTF-16 và UTF-32 có các biến thể cho tuổi thọ .
UTF-32, UTF-32LE, UTF-32BE
Mã hóa đơn giản nhất, mỗi điểm mã được mã hóa đơn giản bằng 4 byte bằng giá trị số của nó. LE / BE đại diện cho endianness (endian nhỏ / endian lớn).
UTF-16, UTF-16LE, UTF-16BE
Điểm mã từ U+0000 - U+FFFF
được mã hóa thành 2 byte bằng giá trị số của nó. Các giá trị lớn hơn được mã hóa bằng một cặp thay thế là các giá trị dành riêng từ đó U+D800 - U+DFFF
. Vì vậy, để mã hóa các điểm lớn hơn U+FFFF
, thuật toán sau có thể được sử dụng (được sao chép một cách không biết xấu hổ từ Wikipedia ):
- 0x010000 bị trừ khỏi điểm mã, để lại một số 20 bit trong phạm vi 0..0x0FFFFF.
- Mười bit trên cùng (một số trong phạm vi 0..0x03FF) được thêm vào 0xD800 để cung cấp đơn vị mã đầu tiên hoặc thay thế dẫn đầu, sẽ nằm trong phạm vi 0xD800..0xDBFF [...].
- Mười bit thấp (cũng trong phạm vi 0..0x03FF) được thêm vào 0xDC00 để cung cấp đơn vị mã thứ hai hoặc thay thế dấu vết, sẽ nằm trong phạm vi 0xDC00..0xDFFF [...].
UTF-8
Điểm mã từ U+0000 - U+007F
được mã hóa thành 1 byte bằng giá trị số của nó. Từ U+0080 - U+07FF
chúng được mã hóa như 110xxxxx 10xxxxxx
, U+0800 - U+FFFF
là 1110xxxx 10xxxxxx 10xxxxxx
, giá trị cao hơn là 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
. Các x
's là các bit từ giá trị số của các điểm mã.
BOM
Dấu thứ tự byte (BOM, U+FEFF
) được sử dụng làm điểm mã đầu tiên để biểu thị tuổi thọ. Theo hướng dẫn FAQ về BOM , BOM sẽ được sử dụng như sau: Đối với UTF-8, UTF-16 and UTF-32
nó là tùy chọn. Nếu BOM vắng mặt trong UTF-16
hoặc UTF-32
, nó được coi là endian lớn. BOM không được xuất hiện trong UTF-16LE, UTF-16BE, UTF-32LE and UTF-32BE
.
Cạm bẫy thường gặp gây UTF không hợp lệ
Nhiều thứ có thể khiến một chuỗi byte là UTF không hợp lệ.
- UTF-8 và UTF-32: Mã hóa trực tiếp các điểm mã thay thế (
U+D800 - U+DFFF
) hoặc điểm mã lớn hơnU+10FFFF
. - UTF-8: Nhiều chuỗi byte không hợp lệ.
- UTF-16: Các cặp thay thế được ghép đôi hoặc ghép cặp không đúng cách.
- BOM: Phải được sử dụng như được chỉ định trong phần mã hóa. Lưu ý rằng khi xuất
UTF-16
hoặcUTF-32
(không có chỉ định cuối cùng được chỉ định), bạn có thể chọn, nhưng với ít endian, bạn phải bao gồm BOM.
Lưu ý rằng các điểm mã không được ký tự và không được gán (cả hai khác biệt với các đại diện thay thế) sẽ được coi như các ký tự thông thường.
''⎕R''⍠'InEnc' 'UTF16BE' 'OutEnc' 'UTF8-BOM'
.