มันถูกต้องดัดแปลง UTF-8?


9

UTF-8เป็นวิธีที่ง่ายในการเข้ารหัส Unicode codepoints ในรูปแบบความกว้างของตัวแปรซึ่งจะไม่ทำให้เกิดความสับสนกับโค้ดที่ไม่รู้ Unicode

ภาพรวม UTF-8

  • ไบต์ในช่วง 1-0x7F โดยรวมจะถูกต้องตามปกติ
  • ไบต์ที่มีรูปแบบบิต10XX XXXXถือว่าเป็นไบต์ต่อเนื่องโดยใช้บิตที่มีนัยสำคัญน้อยที่สุดหกบิตที่ใช้ในการเข้ารหัสส่วนของ codepoint สิ่งเหล่านี้จะต้องไม่ปรากฏขึ้นเว้นแต่จะได้รับการคาดหวังจากไบต์ก่อนหน้า
  • ไบต์ที่มีรูปแบบ110X XXXXคาดว่าหนึ่งไบต์ต่อเนื่องหลังจากนั้น
  • ไบต์ที่มีรูปแบบ1110 XXXXคาดว่าจะมีความต่อเนื่องสองไบต์หลังจากนั้น
  • ไบต์ที่มีรูปแบบ1111 0XXXคาดว่าสามไบต์ต่อเนื่องหลังจากนั้น
  • ไบต์อื่นทั้งหมดไม่ถูกต้องและไม่ควรปรากฏที่ใดก็ได้ในสตรีม UTF-8 5, 6 และ 7 ไบต์เป็นไปได้ในทางทฤษฎี แต่จะไม่ได้รับอนุญาตสำหรับจุดประสงค์ของการท้าทายนี้

การเข้ารหัสที่ยาวนานเกินไป

UTF-8 ยังต้องการให้ codepoint ควรแสดงด้วยจำนวนไบต์ต่ำสุด ลำดับไบต์ใด ๆ ที่สามารถแทนด้วยจำนวนไบต์ที่น้อยกว่านั้นไม่ถูกต้อง แก้ไข UTF-8 เพิ่มข้อยกเว้นหนึ่งข้อสำหรับอักขระ null (U + 0000) ซึ่งควรแสดงเป็นC0 80(การแสดงฐานสิบหก) และแทนที่จะปิดการใช้งาน null null เพื่อปรากฏที่ใดก็ได้ในสตรีม (สิ่งนี้ทำให้เข้ากันได้กับสตริงที่สิ้นสุดด้วยค่า null)

ท้าทาย

คุณต้องสร้างโปรแกรมที่เมื่อได้รับสตริงของไบต์จะพิจารณาว่าสตริงนั้นหมายถึง Modified UTF-8 ที่ถูกต้องหรือไม่และจะส่งกลับค่าความจริงหากถูกต้องและเป็นค่าเท็จ โปรดทราบว่าคุณต้องตรวจสอบการเข้ารหัสที่มากเกินไปและไบต์ว่าง (เนื่องจากนี่คือ Modified UTF-8) คุณไม่จำเป็นต้องถอดรหัสค่า UTF-8

ตัวอย่าง

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

กฎระเบียบ

  • ใช้กฎมาตรฐานและช่องโหว่
  • อินพุตและเอาต์พุตสามารถอยู่ในรูปแบบที่สะดวกใด ๆ ตราบใดที่ค่าทั้งหมดในช่วงไบต์ที่ไม่ได้ลงนาม (0-255) สามารถอ่านได้
    • คุณอาจต้องใช้อาร์เรย์หรือไฟล์แทนสตริงที่สิ้นสุดด้วยค่า null คุณต้องสามารถอ่านค่า null ได้
  • รหัสที่สั้นที่สุดชนะ!
  • โปรดทราบว่าการใช้ builtins เพื่อถอดรหัส UTF-8 ไม่รับประกันว่าจะเป็นไปตามข้อกำหนดที่ให้ไว้ที่นี่ คุณอาจต้องแก้ไขมันและสร้างกรณีพิเศษ

แก้ไข: เพิ่มโบนัสสำหรับการไม่ใช้ builtins ที่ถอดรหัส UTF-8

EDIT2: นำโบนัสออกเนื่องจากมีเพียงคำตอบสนิมเท่านั้นที่ผ่านการรับรองและมันค่อนข้างจะยากที่จะกำหนด


ฉันรออันนี้อยู่
Adám

คุณอาจต้องการเพิ่มกรณีทดสอบด้วยไบต์ที่ไม่ถูกต้องในช่วง 0xF8-0xFF
Arnauld

2
ดูเหมือนว่าตัวแทน (0xD800 - 0xDFFF) และ codepoints ที่เกิน 0x10FFFF นั้นได้รับอนุญาตซึ่งตรงกันข้ามกับข้อมูลจำเพาะ UTF-8 ที่ "ทันสมัย" ฉันคิดว่าสิ่งนี้ควรมีความชัดเจนโดยเฉพาะในกรณีทดสอบเพิ่มเติม
nwellnhof

ตัวอย่างเพิ่มเติมจะมีประโยชน์
ดอนจ้า

"ไบต์ในช่วง 0-0x7F โดยรวมถูกต้องตามปกติ" ควรจะเป็น 1 ถึง 0x7f หรือไม่
อย่าสดใส

คำตอบ:



1

APL (Dyalog Unicode) , 41 39 ไบต์SBCS

ฟังก์ชันนำหน้าเงียบโดยไม่ระบุชื่อ รับค่าสตริง Unicode เป็นอาร์กิวเมนต์โดยที่จุดโค้ดของอักขระแสดงถึงอินพุตไบต์

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

ลองออนไลน์!

'À\x80'⎕R⎕AR eplace C0 80s ด้วยตัวพิมพ์ใหญ่A lphabet

{... } ใช้ฟังก์ชันที่ไม่ระบุชื่อต่อไปนี้โดยที่อาร์กิวเมนต์คือ:

0:: หากมีข้อผิดพลาดเกิดขึ้น:

  0 กลับศูนย์

 ลอง:

  ⎕UCS⍵ แปลงสตริงเป็นจุดโค้ด

  'UTF-8'⎕UCS⍣2 ตีความเป็น UTF-8 ไบต์และแปลงข้อความผลลัพธ์กลับไปเป็นไบต์

  ⌊/ ไบต์ต่ำสุด (ศูนย์ถ้ามีไบต์ว่างอยู่, บวกถ้าไม่, "ไม่มีที่สิ้นสุด" ถ้าสตริงว่าง)

  × เข้าสู่ระบบ (ศูนย์ถ้าเป็นโมฆะ null เป็นหนึ่งถ้าไม่ได้)


สิ่งนี้จะไม่เป็นจริงD9 C0 80 84 C0 80 10หรือ?
Neil

@ ไม่มีมันทำแน่นอน เป็นสิ่งที่ผิดเนื่องจากการลบC0 80ทำให้ไบต์ที่ไม่เกี่ยวข้องติดกันในลักษณะที่ถูกต้องแม้ว่าจะไม่ถูกต้องเมื่อแยกกัน แก้ไข:อัปเดตเพื่อแก้ไขว่าไม่มีค่าใช้จ่ายไบต์
อดัม

ตัวละครบางตัวขึ้นมาบนหน้าจอของฉันเป็นแค่รูปสี่เหลี่ยมหรือกล่องนั่นเป็นเรื่องปกติใช่มั้ย im ใน firefox บน linux APL เป็นภาษาที่น่าสนใจมาก
อย่าสดใส

@donbright จากประสบการณ์ของฉันตัวละคร APL แสดงผลได้อย่างถูกต้องเสมอแม้ว่าบางครั้งอาจน้อยกว่าความสวยงามดังนั้นกล่องเหล่านั้นอาจเป็นเพียงQuad s ซึ่งควรมีสี่หลักในโค้ดหลัก มันควรจะแสดงผลเช่นนี้ และใช่แล้ว APL นั้นยอดเยี่ยมและสนุกมาก คุณสามารถได้อย่างง่ายดายและเรียนรู้อย่างรวดเร็วมันมากเกินไป - เพียงแค่มามากกว่าในAPL ออชาร์ด
อดัม

ใช่พวกเขาเป็นล่าม ขอบคุณ
ดอนสดใส


0

สนิม - 191 ไบต์ 313 ไบต์

ต่อความคิดเห็นด้านล่างต้นฉบับไม่ทำงานอย่างถูกต้อง รุ่นใหม่และปรับปรุง ไม่มีการใช้ห้องสมุดเพราะสนิมอันยิ่งใหญ่ไม่จำเป็นสำหรับคุณและห้องสมุดของคุณ รหัสนี้ใช้การจับคู่รูปแบบกับเครื่องรัฐ โดยการฉีกออกจากข้อมูลจำเพาะ UTF8 อย่างไร้ยางอายหลังจากค้นพบผ่านการอ้างอิงและการสนทนาโดย Jon Skeetเราสามารถคัดลอกตัวอักขระเกือบสำหรับตัวละครลงในบล็อกการจับคู่รูปแบบการจับคู่สนิม ในตอนท้ายเราได้เพิ่มข้อกำหนดพิเศษ Mutf8 ของ Beefster สำหรับ C0 80 เพื่อใช้งาน Ungolfed:

/* 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;

ลองใช้บนสนามเด็กเล่นสนิม


อุปกรณ์ประกอบฉากสำหรับการทำด้วยตนเอง แต่ฉันคิดว่าการตรวจสอบที่นานเกินไปของคุณไม่ถูกต้อง
Beefster

ความท้าทายของคุณท่านที่รักกระตุ้นให้ฉันเลียนแบบและฉันสรุปจดหมายฉบับนี้โดยท้าทายคุณในที่สุดของฉันในการแก้ไขเมื่อคนที่จะเปิดเผยคำถามของคุณมากขึ้นโผงผาง ( bit.ly/2T8tXhO )
ดอนสดใส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.