Nó có hợp lệ sửa đổi UTF-8 không?


9

UTF-8 là một cách tương đối đơn giản để mã hóa các điểm mã Unicode theo định dạng có độ rộng thay đổi sao cho nó không dễ nhầm lẫn mã không nhận biết Unicode.

Tổng quan về UTF-8

  • Byte trong phạm vi 1-0x7F, bao gồm, thường có giá trị
  • Byte với mẫu bit 10XX XXXXđược coi là byte tiếp tục, với sáu bit có ý nghĩa nhỏ nhất được sử dụng để mã hóa một phần của một điểm mã. Chúng không được xuất hiện trừ khi chúng được mong đợi bởi một byte trước đó.
  • Byte với mẫu 110X XXXXmong đợi một byte tiếp tục sau đó
  • Byte với mẫu 1110 XXXXmong đợi hai byte tiếp tục sau đó
  • Byte với mẫu 1111 0XXXmong đợi ba byte tiếp tục sau đó
  • Tất cả các byte khác không hợp lệ và sẽ không xuất hiện ở bất kỳ đâu trong luồng UTF-8. Về lý thuyết, các cụm 5, 6 và 7 byte có thể, nhưng sẽ không được phép cho các mục đích của thử thách này.

Mã hóa quá dài

UTF-8 cũng yêu cầu một mật mã phải được biểu diễn với số byte tối thiểu. Bất kỳ chuỗi byte nào có thể được biểu diễn với ít byte hơn đều không hợp lệ. UTF-8 đã sửa đổi thêm một ngoại lệ cho ký tự null (U + 0000), được thể hiện dưới dạng C0 80(biểu diễn hex)) và thay vào đó không cho phép các byte rỗng xuất hiện ở bất kỳ đâu trong luồng. (Điều này làm cho nó tương thích với các chuỗi kết thúc null)

Thử thách

Bạn phải tạo một chương trình, khi được cung cấp một chuỗi byte, sẽ xác định xem chuỗi đó có đại diện cho UTF-8 đã sửa đổi hợp lệ hay không và sẽ trả về giá trị trung thực nếu hợp lệ và giá trị sai lệch. Lưu ý rằng bạn phải kiểm tra mã hóa quá dài và byte rỗng (vì đây là UTF-8 đã sửa đổi). Bạn không cần giải mã các giá trị UTF-8.

Ví dụ

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')

Quy tắc

  • Quy tắc chuẩn và sơ hở áp dụng
  • Đầu vào và đầu ra có thể ở bất kỳ định dạng thuận tiện nào miễn là tất cả các giá trị trong phạm vi byte không dấu (0-255) có thể được đọc.
    • Bạn có thể cần phải sử dụng một mảng hoặc tệp chứ không phải là một chuỗi kết thúc null. Bạn cần có khả năng đọc byte rỗng.
  • Mã ngắn nhất sẽ thắng!
  • Lưu ý rằng việc sử dụng nội dung để giải mã UTF-8 không được đảm bảo tuân thủ các yêu cầu được đưa ra ở đây. Bạn có thể cần phải làm việc xung quanh nó và tạo ra các trường hợp đặc biệt.

EDIT: phần thưởng được thêm vào khi không sử dụng nội dung giải mã UTF-8

EDIT2: đã xóa phần thưởng vì chỉ có câu trả lời Rust đủ điều kiện và thật khó để xác định.


Tôi đã chờ đợi điều này.
Adám

Bạn có thể muốn thêm một trường hợp thử nghiệm với một byte không hợp lệ trong phạm vi 0xF8-0xFF.
Arnauld

2
Dường như các chất thay thế (0xD800 - 0xDFFF) và các loại tiền mã hóa vượt quá 0x10FFFF đều được cho phép, trái với thông số UTF-8 "hiện đại". Tôi nghĩ rằng điều này nên được làm rõ, lý tưởng với các trường hợp thử nghiệm bổ sung.
nwellnhof

nhiều ví dụ khác sẽ hữu ích
đừng sáng

"Byte trong phạm vi 0-0x7F, bao gồm, thường có giá trị" có được coi là 1 đến 0x7f không?
don sáng

Câu trả lời:



1

APL (Dyalog Unicode) , 41 39 byte SBCS

Chức năng tiền tố ẩn danh. Lấy một chuỗi Unicode làm đối số trong đó các điểm mã của các ký tự đại diện cho các byte đầu vào.

{0::0⋄×⌊/'UTF-8'UCS2UCS⍵}'À\x80'RA

Hãy thử trực tuyến!

'À\x80'⎕R⎕AR eplace C0 80s với chữ hoa A lph.us

{... } áp dụng các chức năng ẩn danh sau đây, nơi mà các đối số là :

0:: nếu có lỗi xảy ra:

  0 trả về số không

 thử:

  ⎕UCS⍵ chuyển đổi chuỗi thành điểm mã

  'UTF-8'⎕UCS⍣2 diễn giải dưới dạng byte UTF-8 và chuyển đổi văn bản kết quả thành byte

  ⌊/ byte thấp nhất (không nếu có byte rỗng, dương nếu không, "vô cực" nếu chuỗi rỗng)

  × dấu (không nếu có byte null, một nếu không)


Điều này sẽ không trở lại sự thật cho D9 C0 80 84 C0 80 10?
Neil

@Neil Nó thực sự. Điều đó có sai không vì việc xóa C0 80làm cho các byte không liên quan được liền kề theo cách hợp lệ, mặc dù chúng không hợp lệ khi tách rời? Chỉnh sửa: Cập nhật để sửa lỗi mà không mất chi phí byte.
Adám

Một số nhân vật xuất hiện trên màn hình của tôi dưới dạng hình chữ nhật hoặc hình hộp, điều đó có bình thường không? tôi trong firefox trên linux. APL là một ngôn ngữ rất thú vị.
don sáng

@donbright Theo kinh nghiệm của tôi, các ký tự APL luôn hiển thị chính xác, ngay cả khi đôi khi kém đẹp, do đó, các hộp đó có lẽ chỉ là Quad trong số đó phải có bốn trong mã chính. Nó sẽ hiển thị như thế này . Và vâng, APL thật tuyệt vời, và rất nhiều niềm vui. Bạn cũng có thể dễ dàng và nhanh chóng tìm hiểu nó - chỉ cần xuất hiện trong APL Orchard .
Adám

vâng họ là quads. cảm ơn.
don sáng


0

Rust - 191 byte 313 byte

Mỗi bình luận dưới đây ban đầu không hoạt động đúng. Phiên bản mới và cải tiến. Không có thư viện nào được sử dụng, vì Mighty Rust không cần bạn và thư viện của bạn. Mã này sử dụng khớp mẫu với máy trạng thái. Bằng cách xấu hổ xé toạc thông số UTF8 , sau khi tìm thấy nó thông qua tham chiếu và thảo luận của Jon Skeet , chúng ta có thể sao chép thông số gần như ký tự cho nhân vật vào khối khớp mẫu phù hợp. Cuối cùng, chúng tôi thêm vào yêu cầu Mutf8 đặc biệt của Beefster cho C0 80 để được coi là hợp lệ. Ung dung:

/* http://www.unicode.org/versions/corrigendum1.html
 Code Points        1st Byte    2nd Byte    3rd Byte    4th Byte
U+0000..U+007F      00..7F           
U+0080..U+07FF      C2..DF      80..BF           
U+0800..U+0FFF      E0          A0..BF      80..BF       
U+1000..U+FFFF      E1..EF      80..BF      80..BF       
U+10000..U+3FFFF    F0          90..BF      80..BF      80..BF
U+40000..U+FFFFF    F1..F3      80..BF      80..BF      80..BF
U+100000..U+10FFFF  F4          80..8F      80..BF      80..BF
*/

let m=|v:&Vec<u8>|v.iter().fold(0, |s, b| match (s, b) {
        (0, 0x01..=0x7F) => 0,
        (0, 0xc2..=0xdf) => 1,
        (0, 0xe0) => 2,
        (0, 0xe1..=0xef) => 4,
        (0, 0xf0) => 5,
        (0, 0xf1..=0xf3) => 6,
        (0, 0xf4) => 7,
        (1, 0x80..=0xbf) => 0,
        (2, 0xa0..=0xbf) => 1,
        (4, 0x80..=0xbf) => 1,
        (5, 0x90..=0xbf) => 4,
        (6, 0x80..=0xbf) => 4,
        (7, 0x80..=0x8f) => 4,
        (0, 0xc0) => 8, // beefster mutf8 null
        (8, 0x80) => 0, // beefster mutf8 null
        _ => -1,
    })==0;

thử nó trên sân chơi rỉ sét


Đạo cụ để làm điều đó bằng tay, nhưng tôi nghĩ rằng kiểm tra quá dài của bạn là không chính xác.
Beefster

Thử thách của bạn, thưa ông, kích thích tôi bắt chước, và tôi kết thúc bức thư này bằng cách thách thức bạn, đến lượt tôi, để sửa chữa một người đàn ông sẽ phơi bày câu hỏi của bạn một cách thẳng thắn hơn ( bit.ly/2T8tXhO )
sáng
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.