Method: XZ::StreamReader#read

Defined in:
lib/facter/util/ruby-xz-1.0.0/lib/xz/stream_reader.rb

#read(length = nil, outbuf = String.new) ⇒ Object

Mostly like IO#read. The length parameter refers to the amount of decompressed bytes to read, not the amount of bytes to read from the compressed data. That is, if you request a read of 50 bytes, you will receive a string with a maximum length of 50 bytes, regardless of how many bytes this was in compressed form.

Return values are as per IO#read.



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/facter/util/ruby-xz-1.0.0/lib/xz/stream_reader.rb', line 203

def read(length = nil, outbuf = String.new)
  return "".force_encoding(Encoding::BINARY) if length == 0 # Shortcut; retval as per IO#read.

  # Note: Querying the underlying IO as early as possible allows to
  # have Ruby's own IO exceptions to bubble up.
  if length
    return nil if eof? # In line with IO#read
    outbuf.force_encoding(Encoding::BINARY) # As per IO#read docs

    # The user's request is in decompressed bytes, so it doesn't matter
    # how much is actually read from the compressed file.
    if @delegate_io.eof?
      data   = ""
      action = XZ::LibLZMA::LZMA_FINISH
    else
      data   = @delegate_io.read(XZ::CHUNK_SIZE)
      action = @delegate_io.eof? ? XZ::LibLZMA::LZMA_FINISH : XZ::LibLZMA::LZMA_RUN
    end

    lzma_code(data, action) { |decompressed| @readbuf << decompressed }

    # If the requested amount has been read, return it.
    # Also return if EOF has been reached. Note that
    # String#slice! will clear the string to an empty one
    # if `length' is greater than the string length.
    # If EOF is not yet reached, try reading and decompresing
    # more data.
    if @readbuf.bytesize >= length || @delegate_io.eof?
      result = @readbuf.slice!(0, length)
      @pos += result.bytesize
      return outbuf.replace(result)
    else
      return read(length, outbuf)
    end
  else
    # Read the entire file and decompress it into memory, returning it.
    while chunk = @delegate_io.read(XZ::CHUNK_SIZE)
      action = @delegate_io.eof? ? XZ::LibLZMA::LZMA_FINISH : XZ::LibLZMA::LZMA_RUN
      lzma_code(chunk, action) { |decompressed| @readbuf << decompressed }
    end

    @pos += @readbuf.bytesize

    # Apply encoding conversion.
    # First, tag the read data with the external encoding.
    @readbuf.force_encoding(@external_encoding)

    # Now, transcode it to the internal encoding if that was requested.
    # Otherwise return it with the external encoding as-is.
    if @internal_encoding
      @readbuf.encode!(@internal_encoding, @transcode_options)
      outbuf.force_encoding(@internal_encoding)
    else
      outbuf.force_encoding(@external_encoding)
    end

    outbuf.replace(@readbuf)
    @readbuf.clear
    @readbuf.force_encoding(Encoding::BINARY) # Back to binary mode for further reading

    return outbuf
  end
end