lib/io/splice.rb in io_splice-3.0.0 vs lib/io/splice.rb in io_splice-3.1.0
- old
+ new
@@ -27,39 +27,42 @@
# copies the contents of the IO object given by +src+ to +dst+
# If +len+ is specified, then only +len+ bytes are copied and
# +EOFError+ is raised if fewer than +len+ bytes could be copied.
# Otherwise the copy will be until EOF is reached on the +src+.
# +src+ and +dst+ must be IO objects or respond to +to_io+
+ #
+ # This is nearly a drop-in replacement for IO.copy_stream (in Ruby 1.9)
+ # but does not take into account userspace I/O buffers nor IO-like
+ # objects with no underlying file descriptor (e.g. StringIO).
def self.copy_stream(src, dst, len = nil, src_offset = nil)
close = []
src.kind_of?(String) and close << (src = File.open(src))
dst.kind_of?(String) and close << (dst = File.open(dst, "w"))
src, dst = src.to_io, dst.to_io
rv = len
- src.sysseek(src_offset) if src_offset
select_args = selectable(src, dst)
if src.stat.pipe? || dst.stat.pipe?
if len
- len -= full(src, dst, len, select_args) until len == 0
+ len -= full(src, dst, len, src_offset, select_args) until len == 0
else
rv = 0
- while n = partial(src, dst, PIPE_CAPA, select_args)
+ while n = partial(src, dst, PIPE_CAPA, src_offset, select_args)
rv += n
end
end
else
r, w = tmp = IO.pipe
close.concat(tmp)
if len
- while len != 0 && n = partial(src, w, len, select_args)
- len -= full(r, dst, n, select_args)
+ while len != 0 && n = partial(src, w, len, src_offset, select_args)
+ len -= full(r, dst, n, nil, select_args)
end
else
rv = 0
- while n = partial(src, w, PIPE_CAPA, select_args)
- rv += full(r, dst, n, select_args)
+ while n = partial(src, w, PIPE_CAPA, src_offset, select_args)
+ rv += full(r, dst, n, nil, select_args)
end
end
end
rv
@@ -74,14 +77,14 @@
# Raises +EOFError+ if end of file is reached.
# bytes. Returns the number of bytes actually spliced (always +len+)
# The +_select_args+ parameter is reserved for internal use and
# may be removed in future versions. Do not write code that
# depends on +_select_args+.
- def self.full(src, dst, len, _select_args = selectable(src, dst))
+ def self.full(src, dst, len, src_offset, _select_args = selectable(src, dst))
nr = len
while nr > 0
- n = partial(src, dst, nr, _select_args) or
+ n = partial(src, dst, nr, src_offset, _select_args) or
raise EOFError, "end of file reached"
nr -= n
end
len
end
@@ -92,18 +95,19 @@
# Returns the number of bytes actually spliced.
# Like IO#readpartial, this never returns Errno::EAGAIN
# The +_select_args+ parameter is reserved for internal use and
# may be removed in future versions. Do not write code that
# depends on +_select_args+.
- def self.partial(src, dst, len, _select_args = selectable(src, dst))
+ def self.partial(src, dst, len, src_offset,
+ _select_args = selectable(src, dst))
begin
- rv = IO.trysplice(src, nil, dst, nil, len, F_MOVE)
+ rv = IO.trysplice(src, src_offset, dst, nil, len, F_MOVE)
end while rv == :EAGAIN and IO.select(*_select_args)
rv
end
# returns an array suitable for splat-ing to IO.select for blocking I/O
- def self.selectable(src, dst)
+ def self.selectable(src, dst) # :nodoc:
rv = []
src.stat.pipe? or rv[0] = [ src ]
dst.stat.pipe? or rv[1] = [ dst ]
rv
end