mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
Replace manual byte-level scan_id/skip_id with regex — C-level StringScanner.scan is faster than Ruby-level byte scanning\n\nResult: {"status":"keep","combined_µs":4185,"parse_µs":2943,"render_µs":1242,"allocations":25535}
This commit is contained in:
+7
-29
@@ -90,31 +90,21 @@ module Liquid
|
|||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Regex for identifier: [a-zA-Z_][\w-]*\??
|
||||||
|
ID_REGEX = /[a-zA-Z_][\w-]*\??/
|
||||||
|
|
||||||
# ── Identifiers ─────────────────────────────────────────────────
|
# ── Identifiers ─────────────────────────────────────────────────
|
||||||
# Skip an identifier without allocating a string. Returns length skipped, or 0.
|
# Skip an identifier without allocating a string. Returns length skipped, or 0.
|
||||||
def skip_id
|
def skip_id
|
||||||
start = @ss.pos
|
@ss.skip(ID_REGEX) || 0
|
||||||
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
|
end
|
||||||
|
|
||||||
# Check if next id matches expected string, consume if so. No allocation.
|
# Check if next id matches expected string, consume if so. No allocation.
|
||||||
def expect_id(expected)
|
def expect_id(expected)
|
||||||
start = @ss.pos
|
start = @ss.pos
|
||||||
len = skip_id
|
if @ss.skip(ID_REGEX) == expected.bytesize
|
||||||
if len == expected.bytesize
|
|
||||||
match = true
|
match = true
|
||||||
len.times do |i|
|
expected.bytesize.times do |i|
|
||||||
if @source.getbyte(start + i) != expected.getbyte(i)
|
if @source.getbyte(start + i) != expected.getbyte(i)
|
||||||
match = false
|
match = false
|
||||||
break
|
break
|
||||||
@@ -129,19 +119,7 @@ module Liquid
|
|||||||
# Scan a single identifier: [a-zA-Z_][\w-]*\??
|
# Scan a single identifier: [a-zA-Z_][\w-]*\??
|
||||||
# Returns the string or nil if not at an identifier
|
# Returns the string or nil if not at an identifier
|
||||||
def scan_id
|
def scan_id
|
||||||
start = @ss.pos
|
@ss.scan(ID_REGEX)
|
||||||
b = @ss.peek_byte
|
|
||||||
return 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
|
|
||||||
@source.byteslice(start, @ss.pos - start)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Scan a tag name: '#' or \w+
|
# Scan a tag name: '#' or \w+
|
||||||
|
|||||||
Reference in New Issue
Block a user