Skip to content

Commit 2281d7f

Browse files
author
Christopher Doris
committed
better indexing and iteration for StaticString
1 parent 3b31fef commit 2281d7f

File tree

1 file changed

+61
-9
lines changed

1 file changed

+61
-9
lines changed

src/utils.jl

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,19 +197,71 @@ module Utils
197197

198198
Base.codeunit(x::StaticString{T}) where {T} = T
199199

200-
function Base.iterate(x::StaticString, st::Union{Nothing,Tuple}=nothing)
201-
if st === nothing
202-
s = String(x)
203-
z = iterate(s)
200+
function Base.isvalid(x::StaticString{UInt8,N}, i::Int) where {N}
201+
if i < 1 || i > N
202+
return false
203+
end
204+
cs = x.codeunits
205+
c = @inbounds cs[i]
206+
if all(iszero, (cs[j] for j in i:N))
207+
return false
208+
elseif (c & 0x80) == 0x00
209+
return true
210+
elseif (c & 0x40) == 0x00
211+
return false
212+
elseif (c & 0x20) == 0x00
213+
return @inbounds (i N-1) && ((cs[i+1] & 0xC0) == 0x80)
214+
elseif (c & 0x10) == 0x00
215+
return @inbounds (i N-2) && ((cs[i+1] & 0xC0) == 0x80) && ((cs[i+2] & 0xC0) == 0x80)
216+
elseif (c & 0x08) == 0x00
217+
return @inbounds (i N-3) && ((cs[i+1] & 0xC0) == 0x80) && ((cs[i+2] & 0xC0) == 0x80) && ((cs[i+3] & 0xC0) == 0x80)
204218
else
205-
s, st0 = st
206-
z = iterate(s, st0)
219+
return false
207220
end
208-
if z === nothing
221+
return false
222+
end
223+
224+
function Base.iterate(x::StaticString{UInt8,N}, i::Int=1) where {N}
225+
i > N && return
226+
cs = x.codeunits
227+
c = @inbounds cs[i]
228+
if all(iszero, (cs[j] for j in i:N))
229+
return
230+
elseif (c & 0x80) == 0x00
231+
return (reinterpret(Char, UInt32(c) << 24), i+1)
232+
elseif (c & 0x40) == 0x00
209233
nothing
234+
elseif (c & 0x20) == 0x00
235+
if @inbounds (i N-1) && ((cs[i+1] & 0xC0) == 0x80)
236+
return (reinterpret(Char, (UInt32(cs[i]) << 24) | (UInt32(cs[i+1]) << 16)), i+2)
237+
end
238+
elseif (c & 0x10) == 0x00
239+
if @inbounds (i N-2) && ((cs[i+1] & 0xC0) == 0x80) && ((cs[i+2] & 0xC0) == 0x80)
240+
return (reinterpret(Char, (UInt32(cs[i]) << 24) | (UInt32(cs[i+1]) << 16) | (UInt32(cs[i+2]) << 8)), i+3)
241+
end
242+
elseif (c & 0x08) == 0x00
243+
if @inbounds (i N-3) && ((cs[i+1] & 0xC0) == 0x80) && ((cs[i+2] & 0xC0) == 0x80) && ((cs[i+3] & 0xC0) == 0x80)
244+
return (reinterpret(Char, (UInt32(cs[i]) << 24) | (UInt32(cs[i+1]) << 16) | (UInt32(cs[i+2]) << 8) | UInt32(cs[i+3])), i+4)
245+
end
246+
end
247+
throw(StringIndexError(x, i))
248+
end
249+
250+
function Base.isvalid(x::StaticString{UInt32,N}, i::Int) where {N}
251+
i < 1 && return false
252+
cs = x.codeunits
253+
return !all(iszero, (cs[j] for j in i:N))
254+
end
255+
256+
function Base.iterate(x::StaticString{UInt32,N}, i::Int=1) where {N}
257+
i > N && return
258+
cs = x.codeunits
259+
c = @inbounds cs[i]
260+
if all(iszero, (cs[j] for j in i:N))
261+
return
210262
else
211-
c, newst0 = z
212-
(c, (s, newst0))
263+
return (Char(c), i+1)
213264
end
214265
end
266+
215267
end

0 commit comments

Comments
 (0)