Skip to content

Commit c898b17

Browse files
authored
Add split_each (#23)
1 parent ae95b19 commit c898b17

File tree

4 files changed

+89
-3
lines changed

4 files changed

+89
-3
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "MemoryViews"
22
uuid = "a791c907-b98b-4e44-8f4d-e4c2362c6b2f"
3-
version = "0.3.2"
3+
version = "0.3.3"
44
authors = ["Jakob Nybo Nissen <jakobnybonissen@gmail.com>"]
55

66
[weakdeps]

src/MemoryViews.jl

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
module MemoryViews
22

33
export MemoryView,
4-
ImmutableMemoryView, MutableMemoryView, MemoryKind, IsMemory, NotMemory, inner
4+
ImmutableMemoryView,
5+
MutableMemoryView,
6+
MemoryKind,
7+
IsMemory,
8+
NotMemory,
9+
inner,
10+
split_each
511

6-
public Mutable, Immutable
12+
public Mutable, Immutable, DelimitedIterator
713

814
"""
915
Unsafe
@@ -90,6 +96,8 @@ end
9096
const MutableMemoryView{T} = MemoryView{T, Mutable}
9197
const ImmutableMemoryView{T} = MemoryView{T, Immutable}
9298

99+
_get_mutability(::MemoryView{T, M}) where {T, M} = M
100+
93101
# Mutable mem views can turn into immutable ones, but not vice versa
94102
ImmutableMemoryView(x) = ImmutableMemoryView(MemoryView(x)::MemoryView)
95103
function ImmutableMemoryView(x::MutableMemoryView{T}) where {T}
@@ -180,6 +188,7 @@ MemoryKind(::Type{Union{}}) = NotMemory()
180188
include("construction.jl")
181189
include("basic.jl")
182190
include("experimental.jl")
191+
include("delimited.jl")
183192
include("base_arrays.jl")
184193
include("io.jl")
185194

src/delimited.jl

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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

test/runtests.jl

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ using MemoryViews
44
using Aqua
55
using StringViews: StringView
66

7+
using MemoryViews: DelimitedIterator, Mutable, Immutable
8+
79
MemoryViews.MemoryView(s::GenericString) = MemoryView(s.string)
810

911
MUT_BACKINGS = Any[
@@ -568,6 +570,21 @@ end
568570
end
569571
end
570572

573+
@testset "split_each" begin
574+
it = split_each(b"abcdba", 0x00)
575+
@test eltype(it) == ImmutableMemoryView{UInt8}
576+
@test it isa DelimitedIterator{UInt8, Immutable}
577+
it = split_each(["abc", "def", "ghi"], "")
578+
@test eltype(it) == MutableMemoryView{String}
579+
@test it isa DelimitedIterator{String, Mutable}
580+
581+
@test collect(split_each(b"", 0x00)) == ImmutableMemoryView{UInt8}[]
582+
@test collect(split_each([1, 2, 3, 3, 4, 5, 2, 3], 3)) == [[1, 2], [], [4, 5, 2], []]
583+
@test collect(split_each(String[], "")) == String[]
584+
@test collect(split_each([1.0, 0.0, 2.0, -0.0, 5], -0.0)) == [[1.0, 0.0, 2.0], [5.0]]
585+
@test collect(split_each([Dict()], Dict())) == [[], []]
586+
end
587+
571588
@testset "Equality" begin
572589
v = rand(UInt, 10)
573590
m1 = MemoryView(v)

0 commit comments

Comments
 (0)