Skip to content

Commit 3cd123d

Browse files
committed
expose findfirst findnext for UInt8 vector
1 parent 0336f67 commit 3cd123d

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

base/strings/search.jl

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,26 @@ true
123123
"""
124124
findfirst(ch::AbstractChar, string::AbstractString) = findfirst(==(ch), string)
125125

126+
"""
127+
findfirst(pattern::AbstractVector{T}, A::AbstractVector{T}) where {T<:Union{Int8,UInt8}}
128+
129+
Find the first occurrence of `pattern` in `ary`.
130+
131+
!!! compat "Julia 1.6"
132+
This method requires at least Julia 1.6.
133+
134+
# Examples
135+
```jldoctest
136+
julia> findfirst([0x52, 0x62], [0x40, 0x52, 0x62, 0x63])
137+
2:3
138+
```
139+
"""
140+
function findfirst(pattern::AbstractVector{T}, A::AbstractVector{T}) where {T<:Union{Int8,UInt8}}
141+
_search(A, pattern, firstindex(A))
142+
end
143+
144+
145+
126146
# AbstractString implementation of the generic findnext interface
127147
function findnext(testf::Function, s::AbstractString, i::Integer)
128148
i = Int(i)
@@ -174,9 +194,12 @@ function _searchindex(s::String, t::String, i::Integer)
174194
_searchindex(unsafe_wrap(Vector{UInt8},s), unsafe_wrap(Vector{UInt8},t), i)
175195
end
176196

177-
function _searchindex(s::ByteArray, t::ByteArray, i::Integer)
178-
n = sizeof(t)
179-
m = sizeof(s)
197+
function _searchindex(s::AbstractVector{T},
198+
t::AbstractVector{T},
199+
i::Integer) where T <:Union{Int8,UInt8}
200+
201+
n = length(t)
202+
m = length(s)
180203

181204
if n == 0
182205
return 1 <= i <= m+1 ? max(1, i) : 0
@@ -194,7 +217,7 @@ function _searchindex(s::ByteArray, t::ByteArray, i::Integer)
194217
bloom_mask = UInt64(0)
195218
skip = n - 1
196219
tlast = _nthbyte(t,n)
197-
for j in 1:n
220+
for j in firstindex(s):n
198221
bloom_mask |= _search_bloom_mask(_nthbyte(t,j))
199222
if _nthbyte(t,j) == tlast && j < n
200223
skip = n - j - 1
@@ -235,8 +258,8 @@ function _searchindex(s::ByteArray, t::ByteArray, i::Integer)
235258
0
236259
end
237260

238-
function _search(s::Union{AbstractString,ByteArray},
239-
t::Union{AbstractString,AbstractChar,Int8,UInt8},
261+
function _search(s::Union{AbstractString,AbstractVector{<:Union{Int8,UInt8}}},
262+
t::Union{AbstractString,AbstractChar,AbstractVector{<:Union{Int8,UInt8}}},
240263
i::Integer)
241264
idx = _searchindex(s,t,i)
242265
if isempty(t)
@@ -296,6 +319,28 @@ julia> findnext('o', "Hello to the world", 6)
296319
findnext(ch::AbstractChar, string::AbstractString, ind::Integer) =
297320
findnext(==(ch), string, ind)
298321

322+
"""
323+
findnext(pattern::AbstractVector{T}, A::AbstractVector{T}, start::Integer) where T<:Union{Int8,UInt8}
324+
325+
Find the next occurrence of `pattern` in `A` starting at position `start`.
326+
327+
!!! compat "Julia 1.6"
328+
This method requires at least Julia 1.6.
329+
330+
# Examples
331+
```jldoctest
332+
julia> findnext([0x52, 0x62], [0x52, 0x62, 0x72], 5) === nothing
333+
true
334+
335+
julia> findnext([0x52, 0x62], [0x40, 0x52, 0x62, 0x52, 0x62], 3)
336+
4:5
337+
```
338+
"""
339+
function findnext(pattern::AbstractVector{T},
340+
A::AbstractVector{T}, ind::Integer) where T<:Union{Int8,UInt8}
341+
_search(A, pattern, ind)
342+
end
343+
299344
"""
300345
findlast(pattern::AbstractString, string::AbstractString)
301346

test/strings/search.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,3 +408,13 @@ for T = (UInt, BigInt)
408408
@test findprev(isletter, astr, T(x)) isa Int
409409
end
410410
end
411+
412+
# issue 37280
413+
let A = [0x40, 0x52, 0x62, 0x52, 0x62]
414+
@test findfirst([0x99], A) === nothing
415+
@test findfirst([0x52], A) == 2:2
416+
@test findfirst([0x52, 0x62], A) == 2:3
417+
@test findnext([0x52, 0x62], A, 2) == 2:3
418+
@test findnext([0x52, 0x62], A, 3) == 4:5
419+
@test findnext([0x52, 0x62], A, 5) === nothing
420+
end

0 commit comments

Comments
 (0)