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
6 changes: 5 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
name = "MemoryViews"
uuid = "a791c907-b98b-4e44-8f4d-e4c2362c6b2f"
version = "0.3.7"
version = "0.4.0"
authors = ["Jakob Nybo Nissen <jakobnybonissen@gmail.com>"]

[deps]
LightBoundsErrors = "e21c612c-4641-4669-b9c3-3f4360ced9da"

[weakdeps]
StringViews = "354b36f9-a18e-4713-926e-db85100087ba"
FixedSizeArrays = "3821ddf9-e5b5-40d5-8e25-6813ab96b5e2"
Expand All @@ -18,6 +21,7 @@ Aqua = "0.8.7"
StringViews = "1"
FixedSizeArrays = "1"
LibDeflate = "0.4"
LightBoundsErrors = "1.1"
Test = "1.11"
julia = "1.11"

Expand Down
2 changes: 2 additions & 0 deletions src/MemoryViews.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export MemoryView,

public Mutable, Immutable, DelimitedIterator

using LightBoundsErrors: checkbounds_lightboundserror, throw_lightboundserror

"""
Unsafe

Expand Down
22 changes: 13 additions & 9 deletions src/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ function Base.copy(x::MemoryView)
return typeof(x)(unsafe, memoryref(newmem), x.len)
end

function Base.checkbounds(v::MemoryView, is...)
checkbounds_lightboundserror(v, is...)
end

function Base.getindex(v::MemoryView, i::Integer)
@boundscheck checkbounds(v, i)
ref = @inbounds memoryref(v.ref, i)
Expand Down Expand Up @@ -137,7 +141,7 @@ Base.@propagate_inbounds Base.view(v::MemoryView, idx::AbstractUnitRange) = v[id
function truncate(mem::MemoryView, include_last::Integer)
lst = Int(include_last)::Int
@boundscheck if (lst % UInt) > length(mem) % UInt
throw(BoundsError(mem, lst))
throw_lightboundserror(mem, lst)
end
return typeof(mem)(unsafe, mem.ref, lst)
end
Expand All @@ -147,7 +151,7 @@ end
function truncate_start_nonempty(mem::MemoryView, from::Integer)
frm = Int(from)::Int
@boundscheck if ((frm - 1) % UInt) ≥ length(mem) % UInt
throw(BoundsError(mem, frm))
throw_lightboundserror(mem, frm)
end
newref = @inbounds memoryref(mem.ref, frm)
return typeof(mem)(unsafe, newref, length(mem) - frm + 1)
Expand All @@ -158,7 +162,7 @@ end
function truncate_start(mem::MemoryView, from::Integer)
frm = Int(from)::Int
@boundscheck if ((frm - 1) % UInt) > length(mem) % UInt
throw(BoundsError(mem, frm))
throw_lightboundserror(mem, frm)
end
frm == 1 && return mem
newref = @inbounds memoryref(mem.ref, frm - (from == length(mem) + 1))
Expand All @@ -172,12 +176,12 @@ function Base.unsafe_copyto!(dst::MutableMemoryView{T}, src::MemoryView{T}) wher
end

function Base.copy!(dst::MutableMemoryView{T}, src::MemoryView{T}) where {T}
@boundscheck length(dst) == length(src) || throw(BoundsError(dst, eachindex(src)))
@boundscheck length(dst) == length(src) || throw_lightboundserror(dst, eachindex(src))
return unsafe_copyto!(dst, src)
end

function Base.copyto!(dst::MutableMemoryView{T}, src::MemoryView{T}) where {T}
@boundscheck length(dst) ≥ length(src) || throw(BoundsError(dst, eachindex(src)))
@boundscheck length(dst) ≥ length(src) || throw_lightboundserror(dst, eachindex(src))
return unsafe_copyto!(dst, src)
end

Expand All @@ -195,7 +199,7 @@ end
# Optimised methods that don't boundscheck
function Base.findnext(p::Function, mem::MemoryView, start::Integer)
i = Int(start)::Int
@boundscheck (i < 1 && throw(BoundsError(mem, i)))
@boundscheck (i < 1 && throw_lightboundserror(mem, i))
@inbounds while i <= length(mem)
p(mem[i]) && return i
i += 1
Expand Down Expand Up @@ -238,7 +242,7 @@ Base.@propagate_inbounds function _findnext(
start::Integer,
) where {T <: Union{UInt8, Int8}}
start = Int(start)::Int
@boundscheck(start < 1 && throw(BoundsError(mem, start)))
@boundscheck(start < 1 && throw_lightboundserror(mem, start))
start > length(mem) && return nothing
im = @inbounds truncate_start_nonempty(ImmutableMemoryView(mem), start)
v_ind = @something memchr(im, byte) return nothing
Expand All @@ -260,7 +264,7 @@ end

function Base.findprev(p::Function, mem::MemoryView, start::Integer)
i = Int(start)::Int
@boundscheck (i > length(mem) && throw(BoundsError(mem, i)))
@boundscheck (i > length(mem) && throw_lightboundserror(mem, i))
@inbounds while i > 0
p(mem[i]) && return i
i -= 1
Expand Down Expand Up @@ -298,7 +302,7 @@ Base.@propagate_inbounds function _findprev(
start::Integer,
) where {T <: Union{UInt8, Int8}}
start = Int(start)::Int
@boundscheck (start > length(mem) && throw(BoundsError(mem, start)))
@boundscheck (start > length(mem) && throw_lightboundserror(mem, start))
start < 1 && return nothing
im = @inbounds truncate(ImmutableMemoryView(mem), start)
return memrchr(im, byte)
Expand Down
2 changes: 1 addition & 1 deletion src/construction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,6 @@ MemoryKind(::Type{<:ContiguousSubArray{T, N, P}}) where {T, N, P} = MemoryKind(P
function MemoryView(s::ContiguousSubArray{T, N, P}) where {T, N, P}
memview = MemoryView(parent(s)::P)
inds = only(parentindices(s))
@boundscheck checkbounds(memview.ref.mem, inds)
@boundscheck checkbounds_lightboundserror(memview.ref.mem, inds)
return @inbounds memview[inds]
end
16 changes: 10 additions & 6 deletions src/experimental.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export split_first, split_last, split_at, split_unaligned

Return the first element of `v` and all other elements as a new memory view.

This function will throw a `BoundsError` if `v` is empty.
This function will throw a `LightBoundsError` if `v` is empty.

See also: [`split_last`](@ref)

Expand All @@ -22,7 +22,9 @@ julia> split_first(v[1:1])
(0x01, UInt8[])

julia> split_first(v[1:0])
ERROR: BoundsError: attempt to access 0-element MutableMemoryView{UInt8} at index [1]
ERROR: LightBoundsErrors.LightBoundsError: out-of-bounds indexing: `collection[1]`, where:
* `typeof(collection) == MutableMemoryView{UInt8}`
* `axes(collection) == (Base.OneTo(0),)`
[...]
```
"""
Expand All @@ -36,7 +38,7 @@ end

Return the last element of `v` and all other elements as a new memory view.

This function will throw a `BoundsError` if `v` is empty.
This function will throw a `LightBoundsError` if `v` is empty.

See also: [`split_first`](@ref)

Expand All @@ -51,7 +53,9 @@ julia> split_last(v[1:1])
(0x01, UInt8[])

julia> split_last(v[1:0])
ERROR: BoundsError: attempt to access 0-element MutableMemoryView{UInt8} at index [1]
ERROR: LightBoundsErrors.LightBoundsError: out-of-bounds indexing: `collection[1]`, where:
* `typeof(collection) == MutableMemoryView{UInt8}`
* `axes(collection) == (Base.OneTo(0),)`
[...]
```
"""
Expand All @@ -66,7 +70,7 @@ end
Split a memory view into two at an index.

The first will contain all indices in `1:i-1`, the second `i:end`.
This function will throw a `BoundsError` if `i` is not in `1:end+1`.
This function will throw a `LightBoundsError` if `i` is not in `1:end+1`.

# Examples
```jldoctest
Expand All @@ -78,7 +82,7 @@ julia> split_at(MemoryView(Int8[1, 2, 3]), 4)
```
"""
function split_at(v::MemoryView, i::Int)
@boundscheck checkbounds(1:(lastindex(v) + 1), i)
@boundscheck checkbounds_lightboundserror(1:(lastindex(v) + 1), i)
return (@inbounds(truncate(v, i - 1)), @inbounds(truncate_start(v, i)))
end

Expand Down
31 changes: 16 additions & 15 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ using MemoryViews
using Aqua
using StringViews: StringView
using LibDeflate: LibDeflate
using LightBoundsErrors: LightBoundsError

using MemoryViews: DelimitedIterator, Mutable, Immutable

Expand Down Expand Up @@ -212,7 +213,7 @@ end

@test mem[3] == cu[3]
for i in [-100, -4, -1, 0, length(cu) + 1, length(cu) + 100]
@test_throws BoundsError mem[i]
@test_throws LightBoundsError mem[i]
end
end

Expand Down Expand Up @@ -253,8 +254,8 @@ end
v = mem[Base.OneTo(0)]
@test mem === v

@test_throws BoundsError mem[Base.OneTo(8)]
@test_throws BoundsError mem[Base.OneTo(typemax(Int))]
@test_throws LightBoundsError mem[Base.OneTo(8)]
@test_throws LightBoundsError mem[Base.OneTo(typemax(Int))]

# UInt indexing
v = MemoryView([3, 4, 5, 6, 7])
Expand Down Expand Up @@ -396,15 +397,15 @@ end
@test v1 == v2
@test mem1 == mem2

@test_throws BoundsError copy!(MemoryView([1]), MemoryView([1, 2]))
@test_throws BoundsError copy!(MemoryView([1, 2]), MemoryView([1]))
@test_throws LightBoundsError copy!(MemoryView([1]), MemoryView([1, 2]))
@test_throws LightBoundsError copy!(MemoryView([1, 2]), MemoryView([1]))

# Copyto!
v1 = [4, 2, 6, 7, 9]
v2 = [1, 5, 2, 3]
copyto!(MemoryView(v1), MemoryView(v2))
@test v1 == [1, 5, 2, 3, 9]
@test_throws BoundsError copyto!(MemoryView(v2), MemoryView(v1))
@test_throws LightBoundsError copyto!(MemoryView(v2), MemoryView(v1))

# unsafe_copyto!
v1 = [3, 6, 2, 1]
Expand Down Expand Up @@ -474,8 +475,8 @@ end
@test split_first(mem) == (mem[1], mem[2:end])
@test split_last(mem) == (mem[end], mem[1:(end - 1)])
mem = mem[1:0]
@test_throws BoundsError split_first(mem)
@test_throws BoundsError split_last(mem)
@test_throws LightBoundsError split_first(mem)
@test_throws LightBoundsError split_last(mem)
end

# Split empty mem at
Expand Down Expand Up @@ -526,17 +527,17 @@ end
@test findnext(isodd, mem, 0x04) === nothing
@test findnext(isodd, mem, 10) === nothing

@test_throws BoundsError findnext(isodd, mem, 0)
@test_throws BoundsError findnext(isodd, mem, -1)
@test_throws LightBoundsError findnext(isodd, mem, 0)
@test_throws LightBoundsError findnext(isodd, mem, -1)

@test findprev(isodd, mem, 4) == 3
@test findprev(isodd, mem, 0x03) == 3
@test findprev(isodd, mem, 2) == 1
@test findprev(isodd, mem, 0x00) === nothing
@test findprev(isodd, mem, -10) === nothing

@test_throws BoundsError findprev(isodd, mem, 5)
@test_throws BoundsError findprev(isodd, mem, 7)
@test_throws LightBoundsError findprev(isodd, mem, 5)
@test_throws LightBoundsError findprev(isodd, mem, 7)
end

@testset "Memchr routines" begin
Expand All @@ -547,8 +548,8 @@ end
@test findnext(==(T(2)), mem, 3) == 5
@test findnext(==(T(7)), mem, 4) === nothing
@test findnext(==(T(2)), mem, 7) === nothing
@test_throws BoundsError findnext(iszero, mem, 0)
@test_throws BoundsError findnext(iszero, mem, -3)
@test_throws LightBoundsError findnext(iszero, mem, 0)
@test_throws LightBoundsError findnext(iszero, mem, -3)

@test findlast(iszero, mem) == 4
@test findprev(iszero, mem, 3) === nothing
Expand All @@ -558,7 +559,7 @@ end
@test findprev(==(T(9)), mem, 3) === nothing
@test findprev(==(T(2)), mem, -2) === nothing
@test findprev(iszero, mem, 0) === nothing
@test_throws BoundsError findprev(iszero, mem, 7)
@test_throws LightBoundsError findprev(iszero, mem, 7)
end
mem = MemoryView(Int8[2, 3, -1])
@test findfirst(==(0xff), mem) === nothing
Expand Down
Loading