Skip to content

Commit 57a82a6

Browse files
committed
Address some more reviewer comments
1 parent b341967 commit 57a82a6

File tree

2 files changed

+18
-20
lines changed

2 files changed

+18
-20
lines changed

base/iobuffer.jl

+14-16
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
# This can be done only if the buffer is not seekable
3232

3333
mutable struct GenericIOBuffer{T<:AbstractVector{UInt8}} <: IO
34-
# T should support: getindex, setindex!, length, copyto!, similar, and (optionally) resize!
34+
# T should support: getindex, setindex!, length, copyto!, similar, size and (optionally) resize!
3535
data::T
3636

3737
# The user can take control of `data` out of this struct. When that happens, instead of eagerly allocating
@@ -274,7 +274,7 @@ _similar_data(b::IOBuffer, len::Int) = StringMemory(len)
274274
function copy(b::GenericIOBuffer{T}) where T
275275
if b.reinit
276276
# If buffer is used up, allocate a new size-zero buffer
277-
# Reinit implies wriable, and that ptr, size, offset and mark are already the default values
277+
# Reinit implies writable, and that ptr, size, offset and mark are already the default values
278278
return typeof(b)(_similar_data(b, 0), b.readable, b.writable, b.seekable, b.append, b.maxsize)
279279
elseif b.writable
280280
# Else, we just copy the reachable bytes. If buffer is seekable, all bytes
@@ -443,8 +443,7 @@ filesize(io::GenericIOBuffer) = (io.seekable ? io.size - io.offset : bytesavaila
443443
bytesavailable(io::GenericIOBuffer) = io.size - io.ptr + 1
444444

445445
# Position is zero-indexed, but ptr is one-indexed, hence the -1
446-
# TODO: Document that position for an unseekable stream is invalid, or
447-
# make it error
446+
# TODO: Document that position for an unmarked and unseekable stream is invalid (and make it error?)
448447
position(io::GenericIOBuffer) = io.ptr - io.offset - 1
449448

450449
function skip(io::GenericIOBuffer, n::Integer)
@@ -484,7 +483,6 @@ function seek(io::GenericIOBuffer, n::Int)
484483
return io
485484
end
486485

487-
# TODO: Should check for seekable and error if not
488486
function seekend(io::GenericIOBuffer)
489487
io.ptr = io.size+1
490488
return io
@@ -512,7 +510,6 @@ function _resize!(io::GenericIOBuffer, new_size::Int)
512510
return io
513511
end
514512

515-
# TODO: These errors cannot be converted to LazyString, but it's wasteful to interpolate them here.
516513
function truncate(io::GenericIOBuffer, n::Integer)
517514
io.writable || throw(ArgumentError("truncate failed, IOBuffer is not writeable"))
518515
# Non-seekable buffers can only be constructed with `PipeBuffer`, which is explicitly
@@ -587,21 +584,22 @@ end
587584
size = io.size
588585
data = io.data
589586
to_delete = (mark > -1 ? min(mark, ptr - 1) : ptr - 1)
590-
# Only shift data if:
591-
if (
592-
# It will prevent us from having to resize buffer, or
593-
to_delete >= nshort % Int ||
594-
# We will recover at least 256 bytes, and at least 1/8th
595-
# of the data buffer's total length
596-
(to_delete > data_len >>> 3 && to_delete > 255)
597-
)
587+
588+
# We don't want to shift data too often to avoid making writing O(n),
589+
# so we prefer resizing if the shift would free up too little data.
590+
# Therefore, we prefer to resize if copying gets us less than 32 bytes,
591+
# or less than 1/8th of the data's size.
592+
# But we need to shift data if maxsize prevents us from gaining enough
593+
# space through resizing
594+
can_allocate_enough = (io.maxsize - (io.append ? io.size : io.ptr - 1)) % UInt nshort
595+
if !can_allocate_enough || to_delete max(32, data_len >>> 3)
598596
copyto!(data, 1, data, to_delete + 1, size - to_delete)
599597
io.ptr = ptr - to_delete
600598
io.mark = max(-1, mark - to_delete)
601599
io.size = size - to_delete
600+
nshort -= min(nshort, to_delete % UInt)
601+
iszero(nshort) && return io
602602
end
603-
nshort -= min(nshort, to_delete % UInt)
604-
iszero(nshort) && return io
605603
end
606604
# Don't exceed maxsize. Otherwise, we overshoot the number of bytes needed,
607605
# such that we don't need to resize too often.

test/iobuffer.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -586,16 +586,16 @@ end
586586

587587
@testset "Compacting" begin
588588
# Compacting works
589-
buf = Base.GenericIOBuffer(UInt8[], true, true, false, true, 5)
589+
buf = Base.GenericIOBuffer(UInt8[], true, true, false, true, 20)
590590
mark(buf)
591-
write(buf, "Hello")
591+
write(buf, "Hello"^5)
592592
reset(buf)
593593
unmark(buf)
594594
read(buf, UInt8)
595595
read(buf, UInt8)
596596
write(buf, "a!")
597-
@test length(buf.data) == 5
598-
@test take!(buf) == b"lloa!"
597+
@test length(buf.data) == 20
598+
@test String(take!(buf)) == "llo" * "Hello"^3 * "a!"
599599

600600
# Compacting does not do anything when mark == 0
601601
buf = Base.GenericIOBuffer(UInt8[], true, true, false, true, 5)

0 commit comments

Comments
 (0)