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