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
32 changes: 23 additions & 9 deletions src/CircularArrayBuffers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ mutable struct CircularArrayBuffer{T,N} <: AbstractArray{T,N}
step_size::Int
end

const CircularVectorBuffer{T} = CircularArrayBuffer{T, 1}
const CircularVectorBuffer{T} = CircularArrayBuffer{T,1}

CircularVectorBuffer{T}(n::Integer) where T = CircularArrayBuffer{T}(n)
CircularVectorBuffer{T}(n::Integer) where {T} = CircularArrayBuffer{T}(n)

function CircularArrayBuffer{T}(d::Integer...) where {T}
N = length(d)
Expand Down Expand Up @@ -65,7 +65,7 @@ function Base.empty!(cb::CircularArrayBuffer)
cb
end

function Base.push!(cb::CircularArrayBuffer{T, N}, data) where {T,N}
function Base.push!(cb::CircularArrayBuffer{T,N}, data) where {T,N}
if cb.nframes == capacity(cb)
cb.first = (cb.first == capacity(cb) ? 1 : cb.first + 1)
else
Expand All @@ -83,22 +83,22 @@ function Base.push!(cb::CircularArrayBuffer{T, N}, data) where {T,N}
cb
end

function Base.append!(cb::CircularArrayBuffer{T, N}, data) where {T,N}
d, r = divrem(length(data) , cb.step_size)
function Base.append!(cb::CircularArrayBuffer{T,N}, data) where {T,N}
d, r = divrem(length(data), cb.step_size)
@assert r == 0
if length(data) >= length(cb.buffer)
cb.nframes = capacity(cb)
cb.first = 1
cb.buffer[:] .= @view data[end-length(cb.buffer)+1:end]
else
start_idx = (cb.first-1) * cb.step_size + length(cb) + 1
start_idx = (cb.first - 1) * cb.step_size + length(cb) + 1
end_idx = start_idx + length(data) - 1
if start_idx > length(cb.buffer)
start_idx -= length(cb.buffer)
end_idx -= length(cb.buffer)
end
if end_idx > length(cb.buffer)
n_first_part = length(cb.buffer)-start_idx+1
n_first_part = length(cb.buffer) - start_idx + 1
n_second_part = length(data) - n_first_part
cb.buffer[end-n_first_part+1:end] .= @view data[1:n_first_part]
cb.buffer[1:n_second_part] .= @view data[end-n_second_part+1:end]
Expand All @@ -119,14 +119,28 @@ function Base.append!(cb::CircularArrayBuffer{T, N}, data) where {T,N}
cb
end

function Base.pop!(cb::CircularArrayBuffer{T, N}) where {T,N}
function Base.pop!(cb::CircularArrayBuffer{T,N}) where {T,N}
if cb.nframes <= 0
throw(ArgumentError("buffer must be non-empty"))
else
res = @views cb[ntuple(_ -> (:), N - 1)..., cb.nframes]
res = @views cb.buffer[ntuple(_ -> (:), N - 1)..., _buffer_frame(cb, cb.nframes)]
cb.nframes -= 1
res
end
end

function Base.popfirst!(cb::CircularArrayBuffer{T,N}) where {T,N}
if cb.nframes <= 0
throw(ArgumentError("buffer must be non-empty"))
else
res = @views cb.buffer[ntuple(_ -> (:), N - 1)..., _buffer_frame(cb, 1)]
cb.nframes -= 1
cb.first += 1
if cb.first > capacity(cb)
cb.first = 1
end
res
end
end

end
17 changes: 9 additions & 8 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,17 @@ using Test
@test length(b) == 2
@test b[[1, 2]] == [7, 8]

x = pop!(b)
@test x == 8
x = popfirst!(b)
@test x == 7
@test length(b) == 1
@test b[1] == 7
@test b[1] == 8

x = pop!(b)
@test x == 7
@test x == 8
@test length(b) == 0

@test_throws ArgumentError pop!(b)
@test_throws ArgumentError popfirst!(b)
end

@testset "2D Float64" begin
Expand Down Expand Up @@ -132,21 +133,21 @@ using Test
@test b == reshape([c for x in 5:7 for c in x * A], 2, 2, 3)

x = pop!(b)
@test x == 7 * ones(2,2)
@test x == 7 * ones(2, 2)
@test b == reshape([c for x in 5:6 for c in x * A], 2, 2, 2)
end

@testset "append!" begin
b = CircularArrayBuffer{Int}(2,3)
b = CircularArrayBuffer{Int}(2, 3)
append!(b, zeros(2))
append!(b, 1:4)
@test b == [
0 1 3
0 2 4
]

b = CircularArrayBuffer{Int}(2,3)

b = CircularArrayBuffer{Int}(2, 3)
for i in 1:5
push!(b, fill(i, 2))
end
Expand Down