Cursor: add skip_id, expect_id, skip_fragment for zero-alloc scanning

This commit is contained in:
Tobi Lutke
2026-04-04 17:42:32 -07:00
committed by Chris Pak
parent b0c9f576af
commit 5204033588
+57
View File
@@ -53,6 +53,11 @@ module Liquid
@ss.string = source
end
# Extract a slice from the source (deferred allocation)
def slice(start, len)
@source.byteslice(start, len)
end
# ── Whitespace ──────────────────────────────────────────────────
# Skip spaces/tabs/newlines/cr, return count of newlines skipped
def skip_ws
@@ -80,6 +85,39 @@ module Liquid
end
# ── Identifiers ─────────────────────────────────────────────────
# Skip an identifier without allocating a string. Returns length skipped, or 0.
def skip_id
start = @ss.pos
b = @ss.peek_byte
return 0 unless b && ((b >= 97 && b <= 122) || (b >= 65 && b <= 90) || b == USCORE)
@ss.scan_byte
while (b = @ss.peek_byte)
break unless (b >= 97 && b <= 122) || (b >= 65 && b <= 90) ||
(b >= 48 && b <= 57) || b == USCORE || b == DASH
@ss.scan_byte
end
@ss.scan_byte if @ss.peek_byte == QMARK
@ss.pos - start
end
# Check if next id matches expected string, consume if so. No allocation.
def expect_id(expected)
start = @ss.pos
len = skip_id
if len == expected.bytesize
match = true
len.times do |i|
if @source.getbyte(start + i) != expected.getbyte(i)
match = false
break
end
end
return true if match
end
@ss.pos = start
false
end
# Scan a single identifier: [a-zA-Z_][\w-]*\??
# Returns the string or nil if not at an identifier
def scan_id
@@ -188,6 +226,25 @@ module Liquid
@source.byteslice(start, @ss.pos - start)
end
# Skip a fragment without allocating. Returns length skipped, or 0.
def skip_fragment
b = @ss.peek_byte
return 0 unless b
start = @ss.pos
if b == QUOTE_S || b == QUOTE_D
quote = b
@ss.scan_byte
@ss.scan_byte while (b = @ss.peek_byte) && b != quote
@ss.scan_byte if @ss.peek_byte == quote
else
while (b = @ss.peek_byte)
break if b == SPACE || b == TAB || b == NL || b == CR || b == COMMA || b == PIPE
@ss.scan_byte
end
end
@ss.pos - start
end
# Scan a "QuotedFragment" — a quoted string or non-whitespace/comma/pipe run
def scan_fragment
b = @ss.peek_byte