rubyzip/lib/zip/ioextras.rb

187 lines
4.7 KiB
Ruby
Raw Normal View History

2013-06-03 02:33:03 +08:00
module Zip
module IOExtras #:nodoc:
2013-06-03 02:33:03 +08:00
CHUNK_SIZE = 131072
2005-08-06 17:12:07 +08:00
2013-06-03 02:33:03 +08:00
RANGE_ALL = 0..-1
2013-06-03 02:33:03 +08:00
def self.copy_stream(ostream, istream)
s = ''
ostream.write(istream.read(CHUNK_SIZE, s)) until istream.eof?
end
2005-08-06 17:12:07 +08:00
2013-06-03 02:33:03 +08:00
def self.copy_stream_n(ostream, istream, nbytes)
s = ''
toread = nbytes
while (toread > 0 && !istream.eof?)
tr = toread > CHUNK_SIZE ? CHUNK_SIZE : toread
ostream.write(istream.read(tr, s))
toread -= tr
end
end
2005-08-06 17:12:07 +08:00
2013-06-03 02:33:03 +08:00
# Implements kind_of? in order to pretend to be an IO object
module FakeIO
def kind_of?(object)
object == IO || super
end
end
2013-06-03 02:33:03 +08:00
# Implements many of the convenience methods of IO
# such as gets, getc, readline and readlines
# depends on: input_finished?, produce_input and read
module AbstractInputStream
include Enumerable
include FakeIO
def initialize
super
@lineno = 0
@pos = 0
@output_buffer = ""
end
2013-06-03 02:33:03 +08:00
attr_accessor :lineno
attr_reader :pos
def read(numberOfBytes = nil, buf = nil)
tbuf = nil
if @output_buffer.bytesize > 0
if numberOfBytes <= @output_buffer.bytesize
tbuf = @output_buffer.slice!(0, numberOfBytes)
else
numberOfBytes -= @output_buffer.bytesize if (numberOfBytes)
rbuf = sysread(numberOfBytes, buf)
tbuf = @output_buffer
tbuf << rbuf if (rbuf)
@output_buffer = ""
end
else
2013-06-03 02:33:03 +08:00
tbuf = sysread(numberOfBytes, buf)
end
2006-02-04 17:42:46 +08:00
2013-06-03 02:33:03 +08:00
@pos += tbuf.length
2013-06-03 02:33:03 +08:00
return nil unless (tbuf)
2013-06-03 02:33:03 +08:00
if buf
buf.replace(tbuf)
else
buf = tbuf
end
2011-11-18 04:53:04 +08:00
2013-06-03 02:33:03 +08:00
buf
2012-12-08 10:53:22 +08:00
end
2013-06-03 02:33:03 +08:00
def readlines(aSepString = $/)
retVal = []
each_line(aSepString) { |line| retVal << line }
retVal
end
2011-11-18 04:53:04 +08:00
2013-06-03 02:33:03 +08:00
def gets(aSepString = $/, numberOfBytes = nil)
@lineno = @lineno.next
2011-11-18 04:53:04 +08:00
2013-06-03 02:33:03 +08:00
if numberOfBytes.respond_to?(:to_int)
numberOfBytes = numberOfBytes.to_int
aSepString = aSepString.to_str if aSepString
elsif aSepString.respond_to?(:to_int)
numberOfBytes = aSepString.to_int
aSepString = $/
else
numberOfBytes = nil
aSepString = aSepString.to_str if aSepString
end
2011-11-18 04:53:04 +08:00
2013-06-03 02:33:03 +08:00
return read(numberOfBytes) if aSepString.nil?
aSepString = "#{$/}#{$/}" if aSepString.empty?
bufferIndex = 0
overLimit = (numberOfBytes && @output_buffer.bytesize >= numberOfBytes)
while ((matchIndex = @output_buffer.index(aSepString, bufferIndex)) == nil && !overLimit)
bufferIndex = [bufferIndex, @output_buffer.bytesize - aSepString.bytesize].max
if input_finished?
return @output_buffer.empty? ? nil : flush
end
@output_buffer << produce_input
overLimit = (numberOfBytes && @output_buffer.bytesize >= numberOfBytes)
end
sepIndex = [matchIndex + aSepString.bytesize, numberOfBytes || @output_buffer.bytesize].min
@pos += sepIndex
return @output_buffer.slice!(0...sepIndex)
end
2011-11-18 04:53:04 +08:00
2013-06-03 02:33:03 +08:00
def flush
retVal = @output_buffer
@output_buffer=""
return retVal
end
2013-06-03 02:33:03 +08:00
def readline(aSepString = $/)
retVal = gets(aSepString)
raise EOFError if retVal == nil
retVal
end
2013-06-03 02:33:03 +08:00
def each_line(aSepString = $/)
while true
yield readline(aSepString)
end
rescue EOFError
end
2013-06-03 02:33:03 +08:00
alias_method :each, :each_line
end
2013-06-03 02:33:03 +08:00
# Implements many of the output convenience methods of IO.
# relies on <<
module AbstractOutputStream
include FakeIO
def write(data)
self << data
data.to_s.bytesize
end
2013-06-03 02:33:03 +08:00
def print(*params)
self << params.join($,) << $\.to_s
2011-11-18 04:53:04 +08:00
end
2013-06-03 02:33:03 +08:00
def printf(aFormatString, *params)
self << sprintf(aFormatString, *params)
2011-11-18 04:53:04 +08:00
end
2013-06-03 02:33:03 +08:00
def putc(anObject)
self << case anObject
when Fixnum then
anObject.chr
when String then
anObject
else
raise TypeError, "putc: Only Fixnum and String supported"
end
anObject
end
2013-06-03 02:33:03 +08:00
def puts(*params)
params << "\n" if params.empty?
params.flatten.each do |element|
val = element.to_s
self << val
self << "\n" unless val[-1, 1] == "\n"
end
end
2013-06-03 02:33:03 +08:00
end
2013-06-03 02:33:03 +08:00
end # IOExtras namespace module
end
# Copyright (C) 2002-2004 Thomas Sondergaard
# rubyzip is free software; you can redistribute it and/or
# modify it under the terms of the ruby license.