Replace manual byte-level scan_number with regex — cleaner code, same performance\n\nResult: {"status":"keep","combined_µs":4184,"parse_µs":2931,"render_µs":1253,"allocations":25535}

This commit is contained in:
Tobi Lutke
2026-04-04 17:42:33 -07:00
committed by Chris Pak
parent 14ac591403
commit 28ede9c539
+8 -34
View File
@@ -132,44 +132,18 @@ module Liquid
end end
end end
# Regex for numbers: -?\d+(\.\d+)?
FLOAT_REGEX = /-?\d+\.\d+/
INT_REGEX = /-?\d+/
# ── Numbers ───────────────────────────────────────────────────── # ── Numbers ─────────────────────────────────────────────────────
# Try to scan an integer or float. Returns the number or nil. # Try to scan an integer or float. Returns the number or nil.
def scan_number def scan_number
start = @ss.pos if (s = @ss.scan(FLOAT_REGEX))
b = @ss.peek_byte s.to_f
return unless b elsif (s = @ss.scan(INT_REGEX))
s.to_i
if b == DASH
@ss.scan_byte
b = @ss.peek_byte
unless b && b >= ZERO && b <= NINE
@ss.pos = start
return
end
elsif b >= ZERO && b <= NINE
# ok
else
return
end end
# Scan digits
@ss.scan_byte
@ss.scan_byte while (b = @ss.peek_byte) && b >= ZERO && b <= NINE
if @ss.peek_byte == DOT
@ss.scan_byte
# Must have digit after dot for float
if (b = @ss.peek_byte) && b >= ZERO && b <= NINE
@ss.scan_byte
@ss.scan_byte while (b = @ss.peek_byte) && b >= ZERO && b <= NINE
return @source.byteslice(start, @ss.pos - start).to_f
else
# "123." — integer portion only, rewind past dot
@ss.pos -= 1
end
end
Integer(@source.byteslice(start, @ss.pos - start), 10)
end end
# ── Strings ───────────────────────────────────────────────────── # ── Strings ─────────────────────────────────────────────────────