@@ -180,109 +180,79 @@ size_to_fstrides(elsz::Integer, sz::Tuple{Vararg{Integer}}) =
180180size_to_cstrides (elsz:: Integer , sz:: Tuple{Vararg{Integer}} ) =
181181 isempty (sz) ? () : (size_to_cstrides (elsz * sz[end ], sz[1 : end - 1 ])... , elsz)
182182
183- struct StaticString{T,N} <: AbstractString
184- codeunits:: NTuple{N,T}
185- StaticString {T,N} (codeunits:: NTuple{N,T} ) where {T,N} = new {T,N} (codeunits)
186- end
187-
188- function Base. String (x:: StaticString{T,N} ) where {T,N}
189- ts = x. codeunits
190- n = N
191- while n > 0 && iszero (ts[n])
192- n -= 1
183+ function utf8_allzeros (codeunit:: F , n:: Int , i:: Int ) where {F}
184+ @inbounds for j in i: n
185+ iszero (codeunit (j)) || return false
193186 end
194- cs = T[ts[i] for i = 1 : n]
195- transcode (String, cs)
187+ return true
196188end
197189
198- function Base. convert (:: Type{StaticString{T,N}} , x:: AbstractString ) where {T,N}
199- ts = transcode (T, convert (String, x))
200- n = length (ts)
201- n > N && throw (InexactError (:convert , StaticString{T,N}, x))
202- n > 0 && iszero (ts[n]) && throw (InexactError (:convert , StaticString{T,N}, x))
203- z = zero (T)
204- cs = ntuple (i -> i > n ? z : @inbounds (ts[i]), N)
205- StaticString {T,N} (cs)
206- end
207-
208- StaticString {T,N} (x:: AbstractString ) where {T,N} = convert (StaticString{T,N}, x)
209-
210- Base. ncodeunits (x:: StaticString{T,N} ) where {T,N} = N
211-
212- Base. codeunit (x:: StaticString , i:: Integer ) = x. codeunits[i]
213-
214- Base. codeunit (x:: StaticString{T} ) where {T} = T
215-
216- function Base. isvalid (x:: StaticString{UInt8,N} , i:: Int ) where {N}
217- if i < 1 || i > N
190+ function utf8_isvalid (codeunit:: F , n:: Int , i:: Int ; zeroterminated:: Bool = false ) where {F}
191+ if i < 1 || i > n
218192 return false
219193 end
220- cs = x. codeunits
221- c = @inbounds cs[i]
222- if all (iszero, (cs[j] for j = i: N))
223- return false
224- elseif (c & 0x80 ) == 0x00
194+ zeroterminated && utf8_allzeros (codeunit, n, i) && return false
195+ c = @inbounds codeunit (i)
196+ if (c & 0x80 ) == 0x00
225197 return true
226198 elseif (c & 0x40 ) == 0x00
227199 return false
228200 elseif (c & 0x20 ) == 0x00
229- return @inbounds (i ≤ N - 1 ) && ((cs[i + 1 ] & 0xC0 ) == 0x80 )
201+ return @inbounds (i ≤ n - 1 ) && ((codeunit (i + 1 ) & 0xC0 ) == 0x80 )
230202 elseif (c & 0x10 ) == 0x00
231- return @inbounds (i ≤ N - 2 ) &&
232- ((cs[i + 1 ] & 0xC0 ) == 0x80 ) &&
233- ((cs[i + 2 ] & 0xC0 ) == 0x80 )
203+ return @inbounds (i ≤ n - 2 ) &&
204+ ((codeunit (i + 1 ) & 0xC0 ) == 0x80 ) &&
205+ ((codeunit (i + 2 ) & 0xC0 ) == 0x80 )
234206 elseif (c & 0x08 ) == 0x00
235- return @inbounds (i ≤ N - 3 ) &&
236- ((cs[i + 1 ] & 0xC0 ) == 0x80 ) &&
237- ((cs[i + 2 ] & 0xC0 ) == 0x80 ) &&
238- ((cs[i + 3 ] & 0xC0 ) == 0x80 )
207+ return @inbounds (i ≤ n - 3 ) &&
208+ ((codeunit (i + 1 ) & 0xC0 ) == 0x80 ) &&
209+ ((codeunit (i + 2 ) & 0xC0 ) == 0x80 ) &&
210+ ((codeunit (i + 3 ) & 0xC0 ) == 0x80 )
239211 else
240212 return false
241213 end
242- return false
243214end
244215
245- function Base. iterate (x:: StaticString{UInt8,N} , i:: Int = 1 ) where {N}
246- i > N && return
247- cs = x. codeunits
248- c = @inbounds cs[i]
249- if all (iszero, (cs[j] for j = i: N))
216+ function utf8_iterate (x, codeunit:: F , n:: Int , i:: Int = 1 ; zeroterminated:: Bool = false ) where {F}
217+ i > n && return
218+ c = @inbounds codeunit (i)
219+ if zeroterminated && utf8_allzeros (codeunit, n, i)
250220 return
251221 elseif (c & 0x80 ) == 0x00
252222 return (reinterpret (Char, UInt32 (c) << 24 ), i + 1 )
253223 elseif (c & 0x40 ) == 0x00
254224 nothing
255225 elseif (c & 0x20 ) == 0x00
256- if @inbounds (i ≤ N - 1 ) && ((cs[i + 1 ] & 0xC0 ) == 0x80 )
226+ if @inbounds (i ≤ n - 1 ) && ((codeunit (i + 1 ) & 0xC0 ) == 0x80 )
257227 return (
258- reinterpret (Char, (UInt32 (cs[i]) << 24 ) | (UInt32 (cs[i + 1 ] ) << 16 )),
228+ reinterpret (Char, (UInt32 (codeunit (i)) << 24 ) | (UInt32 (codeunit (i + 1 ) ) << 16 )),
259229 i + 2 ,
260230 )
261231 end
262232 elseif (c & 0x10 ) == 0x00
263- if @inbounds (i ≤ N - 2 ) && ((cs[i + 1 ] & 0xC0 ) == 0x80 ) && ((cs[i + 2 ] & 0xC0 ) == 0x80 )
233+ if @inbounds (i ≤ n - 2 ) && ((codeunit (i + 1 ) & 0xC0 ) == 0x80 ) && ((codeunit (i + 2 ) & 0xC0 ) == 0x80 )
264234 return (
265235 reinterpret (
266236 Char,
267- (UInt32 (cs[i] ) << 24 ) |
268- (UInt32 (cs[i + 1 ] ) << 16 ) |
269- (UInt32 (cs[i + 2 ] ) << 8 ),
237+ (UInt32 (codeunit (i) ) << 24 ) |
238+ (UInt32 (codeunit (i + 1 ) ) << 16 ) |
239+ (UInt32 (codeunit (i + 2 ) ) << 8 ),
270240 ),
271241 i + 3 ,
272242 )
273243 end
274244 elseif (c & 0x08 ) == 0x00
275- if @inbounds (i ≤ N - 3 ) &&
276- ((cs[i + 1 ] & 0xC0 ) == 0x80 ) &&
277- ((cs[i + 2 ] & 0xC0 ) == 0x80 ) &&
278- ((cs[i + 3 ] & 0xC0 ) == 0x80 )
245+ if @inbounds (i ≤ n - 3 ) &&
246+ ((codeunit (i + 1 ) & 0xC0 ) == 0x80 ) &&
247+ ((codeunit (i + 2 ) & 0xC0 ) == 0x80 ) &&
248+ ((codeunit (i + 3 ) & 0xC0 ) == 0x80 )
279249 return (
280250 reinterpret (
281251 Char,
282- (UInt32 (cs[i] ) << 24 ) |
283- (UInt32 (cs[i + 1 ] ) << 16 ) |
284- (UInt32 (cs[i + 2 ] ) << 8 ) |
285- UInt32 (cs[i + 3 ] ),
252+ (UInt32 (codeunit (i) ) << 24 ) |
253+ (UInt32 (codeunit (i + 1 ) ) << 16 ) |
254+ (UInt32 (codeunit (i + 2 ) ) << 8 ) |
255+ UInt32 (codeunit (i + 3 ) ),
286256 ),
287257 i + 4 ,
288258 )
@@ -291,6 +261,45 @@ function Base.iterate(x::StaticString{UInt8,N}, i::Int = 1) where {N}
291261 throw (StringIndexError (x, i))
292262end
293263
264+ struct StaticString{T,N} <: AbstractString
265+ codeunits:: NTuple{N,T}
266+ StaticString {T,N} (codeunits:: NTuple{N,T} ) where {T,N} = new {T,N} (codeunits)
267+ end
268+
269+ function Base. String (x:: StaticString{T,N} ) where {T,N}
270+ ts = x. codeunits
271+ n = N
272+ while n > 0 && iszero (ts[n])
273+ n -= 1
274+ end
275+ cs = T[ts[i] for i = 1 : n]
276+ transcode (String, cs)
277+ end
278+
279+ function Base. convert (:: Type{StaticString{T,N}} , x:: AbstractString ) where {T,N}
280+ ts = transcode (T, convert (String, x))
281+ n = length (ts)
282+ n > N && throw (InexactError (:convert , StaticString{T,N}, x))
283+ n > 0 && iszero (ts[n]) && throw (InexactError (:convert , StaticString{T,N}, x))
284+ z = zero (T)
285+ cs = ntuple (i -> i > n ? z : @inbounds (ts[i]), N)
286+ StaticString {T,N} (cs)
287+ end
288+
289+ StaticString {T,N} (x:: AbstractString ) where {T,N} = convert (StaticString{T,N}, x)
290+
291+ Base. ncodeunits (x:: StaticString{T,N} ) where {T,N} = N
292+
293+ Base. codeunit (x:: StaticString , i:: Integer ) = x. codeunits[i]
294+
295+ Base. codeunit (x:: StaticString{T} ) where {T} = T
296+
297+ Base. isvalid (x:: StaticString{UInt8,N} , i:: Int ) where {N} =
298+ utf8_isvalid (j -> @inbounds (x. codeunits[j]), N, i; zeroterminated = true )
299+
300+ Base. iterate (x:: StaticString{UInt8,N} , i:: Int = 1 ) where {N} =
301+ utf8_iterate (x, j -> @inbounds (x. codeunits[j]), N, i; zeroterminated = true )
302+
294303function Base. isvalid (x:: StaticString{UInt32,N} , i:: Int ) where {N}
295304 i < 1 && return false
296305 cs = x. codeunits
0 commit comments