Module: Zip::IOExtras::AbstractInputStream

Includes:
Enumerable, FakeIO
Included in:
Zip::InputStream, NullInputStream
Defined in:
lib/zip/ioextras/abstract_input_stream.rb

Overview

Implements many of the convenience methods of IO such as gets, getc, read, readline and readlines depends on: input_finished?, produce_input and read

Instance Attribute Summary collapse

Attributes included from FakeIO

#external_encoding, #internal_encoding

Instance Method Summary collapse

Methods included from FakeIO

#kind_of?, #set_encoding

Instance Attribute Details

#linenoObject

Returns (or sets) the current line number in the decompressed (possibly decrypted) data stream. See the Line Number documentation for the IO class for more information.



28
29
30
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 28

def lineno
  @lineno
end

#posObject (readonly)

Returns the current position (in bytes) in the decompressed (possibly decrypted) data stream.



32
33
34
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 32

def pos
  @pos
end

Instance Method Details

#each(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false) ⇒ Object Also known as: each_line

Calls the block with each remaining line read from the stream. Does nothing if already at end-of-stream. See the Line IO documentation in the IO class for more information.

With no arguments given, reads lines as determined by line separator $/. With only string argument sep given, reads lines as determined by line separator sep. See the Line Separator documentation in the IO class for more information. The two special values for sep (nil and "") are honoured.

With only integer argument limit given, limits the number of bytes in each line; see the Line Limit documentation in the IO class for more information.

With arguments sep and limit given, combines the two behaviors.

Optional keyword argument chomp specifies whether line separators are to be omitted.

Returns an Enumerator if no block is given.



199
200
201
202
203
204
205
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 199

def each(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false)
  return to_enum(:each, sep, limit, chomp: chomp) unless block_given?

  while (line = gets(sep, limit, chomp: chomp))
    yield line
  end
end

#eof?Boolean Also known as: eof

Returns true if the stream is positioned at its end, false otherwise. See Position documentation in the IO class for more information.

Returns:

  • (Boolean)


212
213
214
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 212

def eof?
  @output_buffer.empty? && input_finished?
end

#flushObject

:nodoc:



164
165
166
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 164

def flush # :nodoc:
  @output_buffer.slice!(0..)
end

#gets(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false) ⇒ Object

Reads and returns a line from the stream. See the Line IO documentation in the IO class for more information.

With no arguments given, returns the next line as determined by line separator $/, or nil if none.

With only string argument sep given, returns the next line as determined by line separator sep, or nil if none. See the Line Separator documentation in the IO class for more information. The two special values for sep (nil and "") are honoured.

With only integer argument limit given, limits the number of bytes in the line; see the Line Limit documentation in the IO class for more information.

With arguments sep and limit given, combines the two behaviors.

Optional keyword argument chomp specifies whether line separators are to be omitted.



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 118

def gets(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false) # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
  if sep.nil?
    return nil if eof?

    @lineno = @lineno.next
    return read(limit)
  end

  if sep.respond_to?(:to_int)
    limit = sep.to_int
    sep   = $INPUT_RECORD_SEPARATOR
  elsif sep&.empty?
    sep = "#{$INPUT_RECORD_SEPARATOR}#{$INPUT_RECORD_SEPARATOR}"
  end

  encoding = @internal_encoding || @external_encoding

  buffer_index = 0
  while (sep_index = @output_buffer.index(sep, buffer_index)).nil?
    break if limit && @output_buffer.bytesize >= limit

    if input_finished?
      return nil if @output_buffer.empty?

      @lineno = @lineno.next
      @pos += @output_buffer.bytesize
      return @output_buffer.slice!(0..).force_encoding(encoding)
    end

    buffer_index = [buffer_index, @output_buffer.bytesize - sep.bytesize].max
    @output_buffer << produce_input
  end

  limit ||= @output_buffer.bytesize
  cut_index = sep_index ? [sep_index + sep.bytesize, limit].min : limit
  @lineno = @lineno.next
  @pos += cut_index
  data = @output_buffer.slice!(0, cut_index)
  data&.chomp!(sep) if chomp
  data&.force_encoding(encoding)
end

#initialize(**opts) ⇒ Object

Creates a new input stream wrapper.

This method accepts the standard IO encoding options: external_encoding:, internal_encoding: and encoding:.



18
19
20
21
22
23
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 18

def initialize(**opts)
  super
  @lineno        = 0
  @pos           = 0
  @output_buffer = +''.b
end

#read(maxlen = nil, out_string = nil) ⇒ Object

Reads bytes from the stream decompressed (possibly decrypted) data stream. If maxlen is nil, reads all bytes; otherwise, reads up to maxlen bytes. If maxlen is zero, returns an empty string.

Returns a string (either a new string or the given out_string) containing the bytes read. The string's encoding is the unchanged encoding of out_string, if out_string is given; ASCII-8BIT, otherwise.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 42

def read(maxlen = nil, out_string = nil) # rubocop:disable Metrics/PerceivedComplexity,Metrics/CyclomaticComplexity
  return (maxlen.nil? || maxlen.zero? ? '' : nil) if eof?

  tbuf = if @output_buffer.bytesize > 0
           if maxlen && maxlen <= @output_buffer.bytesize
             @output_buffer.slice!(0, maxlen)
           else
             maxlen -= @output_buffer.bytesize if maxlen
             rbuf = produce_input(maxlen)
             out  = @output_buffer
             out << rbuf if rbuf
             @output_buffer = +''.b
             out
           end
         else
           produce_input(maxlen)
         end

  if tbuf.nil? || tbuf.empty?
    return nil if maxlen&.positive?

    return ''
  end

  @pos += tbuf.length

  if out_string.nil?
    tbuf.force_encoding(@internal_encoding || @external_encoding)
  else
    encoding = out_string.encoding
    out_string.replace(tbuf).force_encoding(encoding)
  end
end

#readline(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false) ⇒ Object

Reads a line as with #gets, but raises EOFError if already at end-of-stream.

Optional keyword argument chomp specifies whether line separators are to be omitted.

Raises:

  • (EOFError)


173
174
175
176
177
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 173

def readline(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false)
  raise EOFError if eof?

  gets(sep, limit, chomp: chomp)
end

#readlines(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false) ⇒ Object

Reads and returns all remaining lines from the stream. See the Line IO documentation in the IO class for more information.

With no arguments given, returns lines as determined by line separator $/, or nil if none.

With only string argument sep given, returns lines as determined by line separator sep, or nil if none. See the Line Separator documentation in the IO class for more information. The two special values for sep (nil and "") are honoured.

With only integer argument limit given, limits the number of bytes in each line; see the Line Limit documentation in the IO class for more information.

With arguments sep and limit given, combines the two behaviors.

Optional keyword argument chomp specifies whether line separators are to be omitted.



95
96
97
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 95

def readlines(sep = $INPUT_RECORD_SEPARATOR, limit = nil, chomp: false)
  each(sep, limit, chomp: chomp).to_a
end

#ungetc(byte) ⇒ Object

:nodoc:



160
161
162
# File 'lib/zip/ioextras/abstract_input_stream.rb', line 160

def ungetc(byte) # :nodoc:
  @output_buffer = byte.chr + @output_buffer
end