|
| 1 | +""" |
| 2 | +Iterator struct created by `split_each`. |
| 3 | +Type and parameters are public, but otherwise the interface is defined by `split_each`, |
| 4 | +""" |
| 5 | +struct DelimitedIterator{T, M} |
| 6 | + v::MemoryView{T, M} |
| 7 | + d::T |
| 8 | +end |
| 9 | + |
| 10 | +Base.IteratorSize(::Type{<:DelimitedIterator}) = Base.SizeUnknown() |
| 11 | +Base.eltype(::Type{DelimitedIterator{T, M}}) where {T, M} = MemoryView{T, M} |
| 12 | + |
| 13 | +function Base.iterate(d::DelimitedIterator, state::Int = 1) |
| 14 | + len = length(d.v) |
| 15 | + if state > len |
| 16 | + # Make sure that an empty view has no elements, but that a view ends |
| 17 | + # on the delimiter has an empty element at the end |
| 18 | + return if state > len + 1 || iszero(len) |
| 19 | + nothing |
| 20 | + else |
| 21 | + v = @inbounds d.v[len:(len - 1)] |
| 22 | + (v, state + 1) |
| 23 | + end |
| 24 | + end |
| 25 | + next = findnext(isequal(d.d), d.v, state) |
| 26 | + return if isnothing(next) |
| 27 | + (@inbounds d.v[state:len], len + 2) |
| 28 | + else |
| 29 | + (@inbounds d.v[state:(next - 1)], next + 1) |
| 30 | + end |
| 31 | +end |
| 32 | + |
| 33 | +""" |
| 34 | + split_each(data, x::T) |
| 35 | +
|
| 36 | +Return an iterator over memory-backed data `data` of eltype `T`. |
| 37 | +Returns `MemoryView`s of the same elements as `data`, separated by by `x`. |
| 38 | +Items are compared by `isequal`. |
| 39 | +
|
| 40 | +An empty input `data` yields no elements. Empty elements are otherwise |
| 41 | +yielded. |
| 42 | +
|
| 43 | +# Examples |
| 44 | +```jldoctest |
| 45 | +julia> split_each(b"abbc", UInt8('b')) |> collect |> print |
| 46 | +ImmutableMemoryView{UInt8}[[0x61], [], [0x63]] |
| 47 | +
|
| 48 | +julia> split_each(b"babceb", UInt8('b')) |> collect |> print |
| 49 | +ImmutableMemoryView{UInt8}[[], [0x61], [0x63, 0x65], []] |
| 50 | +
|
| 51 | +julia> split_each(UInt8[], UInt8('b')) |> collect |> print |
| 52 | +MutableMemoryView{UInt8}[] |
| 53 | +``` |
| 54 | +""" |
| 55 | +function split_each(x, d::T) where {T} |
| 56 | + v = MemoryView(x)::MemoryView |
| 57 | + eltype(v) == T || error("MemoryView(x) must be of eltype T") |
| 58 | + M = _get_mutability(v) |
| 59 | + return DelimitedIterator{T, M}(v, d) |
| 60 | +end |
0 commit comments