Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "MemoryViews"
uuid = "a791c907-b98b-4e44-8f4d-e4c2362c6b2f"
version = "0.3.0"
version = "0.3.1"
authors = ["Jakob Nybo Nissen <jakobnybonissen@gmail.com>"]

[weakdeps]
Expand Down
21 changes: 17 additions & 4 deletions src/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ function Base.getindex(v::MemoryView, i::Integer)
end

function Base.similar(::MemoryView{T1, M}, ::Type{T2}, dims::Tuple{Int}) where {T1, T2, M}
len = Int(only(dims))::Int
len = only(dims)
memory = Memory{T2}(undef, len)
MemoryView{T2, M}(unsafe, memoryref(memory), len)
# Note: `similar` needs to construct a mutable memory view, even if the input
# type is not mutable
MemoryView(memory)
end

function Base.empty(::MemoryView{T1, M}, ::Type{T2}) where {T1, T2, M}
Expand Down Expand Up @@ -101,6 +103,8 @@ end
Base.getindex(v::MemoryView, ::Colon) = v
Base.@propagate_inbounds Base.view(v::MemoryView, idx::AbstractUnitRange) = v[idx]

# Efficient way to get `mem[1:include_last]`.
# include_last must be in 0:length(mem)
function truncate(mem::MemoryView, include_last::Integer)
lst = Int(include_last)::Int
@boundscheck if (lst % UInt) > length(mem) % UInt
Expand All @@ -109,6 +113,8 @@ function truncate(mem::MemoryView, include_last::Integer)
typeof(mem)(unsafe, mem.ref, lst)
end

# Efficient way to get `mem[from:end]`.
# From must be in 1:length(mem).
function truncate_start_nonempty(mem::MemoryView, from::Integer)
frm = Int(from)::Int
@boundscheck if ((frm - 1) % UInt) ≥ length(mem) % UInt
Expand All @@ -118,11 +124,14 @@ function truncate_start_nonempty(mem::MemoryView, from::Integer)
typeof(mem)(unsafe, newref, length(mem) - frm + 1)
end

# Efficient way to get `mem[from:end]`.
# From must be in 1:length(mem)+1.
function truncate_start(mem::MemoryView, from::Integer)
frm = Int(from)::Int
@boundscheck if ((frm - 1) % UInt) > length(mem) % UInt
throw(BoundsError(mem, frm))
end
frm == 1 && return mem
newref = @inbounds memoryref(mem.ref, frm - (from == length(mem) + 1))
typeof(mem)(unsafe, newref, length(mem) - frm + 1)
end
Expand Down Expand Up @@ -320,12 +329,16 @@ function Base.reverse!(mem::MutableMemoryView)
end

function Base.reverse(mem::MemoryView)
cp = MutableMemoryView(unsafe, copy(mem))
cp = similar(mem)
stop = length(cp) + 1
@inbounds for i in 1:length(cp)
cp[i] = mem[stop - i]
end
cp
return if mem isa MutableMemoryView
cp
else
ImmutableMemoryView(cp)
end
end

struct ReverseMemoryView{T}
Expand Down
13 changes: 12 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ end
mem = MemoryView("abc")
mem2 = similar(mem)
@test length(mem2) == length(mem)
@test typeof(mem2) == typeof(mem)
@test typeof(mem2) == MutableMemoryView{UInt8}

mem = MemoryView(String["", "", ""])
mem2 = similar(mem, Int, 4)
Expand Down Expand Up @@ -388,10 +388,15 @@ end
@test reverse!(MemoryView(copy(v))) == MemoryView(reverse(v))
mem = MemoryView(v)
rev = reverse(mem)
@test typeof(rev) == typeof(mem)
@test rev.ref != mem.ref
@test rev == reverse(v)
@test_throws Exception reverse!(ImmutableMemoryView(v))
end
mem = MemoryView("abcd")
rev = reverse(mem)
@test rev == b"dcba"
@test rev isa ImmutableMemoryView{UInt8}
end

@testset "Cmp" begin
Expand Down Expand Up @@ -434,6 +439,12 @@ end
@test_throws BoundsError split_first(mem)
@test_throws BoundsError split_last(mem)
end

# Split empty mem at
mem = MemoryView(UInt16[])
(v1, v2) = split_at(mem, 1)
@test v1 == v2
@test isempty(v1)
end

@testset "Split unaligned" begin
Expand Down