อิกัวนาต้นฉบับตัดริบบิ้นข้อมูลตรงหมุดคู่สีอำพัน โดยปล่อยหมุดเดี่ยวให้ผ่านไป

Zig tokenizeSequence: แยกข้อมูลด้วย delimiter หลายไบต์แบบไม่ตัดกลาง

พี่โชว์Engineering

protocol เล็ก ๆ มักคั่น field ด้วยลำดับหลายไบต์ เช่น :: ถ้าใช้ตัวแบ่งแบบ “เจอ colon ตัวใดก็ได้” ข้อมูลอย่างเวลา 10:30 จะถูกตัดผิด std.mem.tokenizeSequence จับ delimiter ทั้งชุดและคืน slice ของ token โดยไม่ allocate สำเนาครับ

WHY: กรรไกรต้องรอหมุดครบคู่

ให้นึกถึงริบบิ้นที่ทำเครื่องหมายตัดด้วยหมุดสองเม็ดติดกัน กรรไกรไม่ควรตัดเมื่อเห็นหมุดเม็ดแรกตัวเดียว tokenizeSequence ต่างจาก tokenizeAny ตรงที่ทุก element ใน delimiter ต้องเรียงติดกันครบชุด

const std = @import("std");

fn collectThree(input: []const u8) ![3][]const u8 {
    var it = std.mem.tokenizeSequence(u8, input, "::");
    const first = it.next() orelse return error.MissingField;
    const second = it.next() orelse return error.MissingField;
    const third = it.next() orelse return error.MissingField;
    if (it.next() != null) return error.TooManyFields;
    return .{ first, second, third };
}

test "sequence delimiter stays intact" {
    const fields = try collectThree("room::10:30::ready");
    try std.testing.expectEqualStrings("room", fields[0]);
    try std.testing.expectEqualStrings("10:30", fields[1]);
    try std.testing.expectEqualStrings("ready", fields[2]);
    try std.testing.expectError(error.MissingField, collectThree("room::::ready"));
    try std.testing.expectError(error.TooManyFields, collectThree("a::b::c::d"));
}

HOW: token ว่างถูกข้าม

คำว่า tokenize หมายถึงข้าม delimiter ที่ติดกันและไม่คืน token ว่าง ดังนั้น room::::ready มีเพียงสอง token ไม่ใช่สาม field ที่ตรงกลางว่าง ถ้า empty field มีความหมาย ให้ใช้ splitSequence แทนและ validate จำนวนช่องตาม schema

token ที่ได้อ้างอิง buffer ต้นฉบับ ห้ามปล่อย buffer หมดอายุแล้วเก็บ slice ไว้ต่อ ส่วน UTF-8 เป็นเพียง byte sequence สำหรับ API นี้ ถ้า delimiter หรือ input อาจตัดกลาง code point ต้องกำหนด encoding contract และ validate ข้อความก่อน parse

Recap

  • ใช้ tokenizeSequence เมื่อ delimiter ต้องตรงทั้งชุด
  • ใช้ splitSequence หากช่องว่างระหว่าง delimiter มีความหมาย
  • จำกัดจำนวน field และขนาด input ก่อน parse
  • รักษาอายุ buffer ให้ยาวกว่า token slices
  • ทดสอบ delimiter ซ้ำ ขาด field เกิน field และข้อมูลที่มี delimiter บางส่วน