Class: IOWindow

Inherits:
IO::LikeHelpers::DelegatedIO
  • Object
show all
Defined in:
lib/archive/support/iowindow.rb

Overview

IOWindow represents an IO object which wraps another one allowing read access to a subset of the data within the stream.

Instance Method Summary collapse

Constructor Details

#initialize(delegate, window_position, window_size, autoclose: true) ⇒ IOWindow

Creates a new instance of this class using delegate as the data source and where window_position and window_size define the location and size of data window respectively.

delegate must be opened for reading and must be seekable. window_position must be an integer greater than or equal to 0. window_size must be an integer greater than or equal to 0.

Raises:

  • (ArgumentError)


15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/archive/support/iowindow.rb', line 15

def initialize(delegate, window_position, window_size, autoclose: true)
  super(delegate, autoclose: autoclose)

  @window_position = Integer(window_position)
  if @window_position < 0
    raise ArgumentError, 'window_position must be at least 0'
  end
  @window_size = Integer(window_size)
  raise ArgumentError, 'window_size must be at least 0' if @window_size < 0

  @pos = 0
end

Instance Method Details

#read(length, buffer: nil, buffer_offset: 0) ⇒ Object

Raises:

  • (EOFError)


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/archive/support/iowindow.rb', line 28

def read(length, buffer: nil, buffer_offset: 0)
  # Error out if the end of the window is reached.
  raise EOFError, 'end of file reached' if @pos >= @window_size

  # Limit the read operation to the window.
  length = @window_size - @pos if @pos + length > @window_size

  # Fill a buffer with the data from the delegate.
  result = super(length, buffer: buffer, buffer_offset: buffer_offset)
  return result if Symbol === result

  @pos += buffer.nil? ? result.bytesize : result

  result
end

#seek(amount, whence = IO::SEEK_SET) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/archive/support/iowindow.rb', line 44

def seek(amount, whence = IO::SEEK_SET)
  # Convert the amount into an absolute position.
  case whence
  when IO::SEEK_SET
    new_pos = amount
  when IO::SEEK_CUR
    new_pos = @pos + amount
  when IO::SEEK_END
    new_pos = @window_size + amount
  end

  # Error out if the position is outside the window.
  if new_pos < 0 || new_pos > @window_size
    raise Errno::EINVAL, 'Invalid argument'
  end

  @pos = super(new_pos + @window_position, IO::SEEK_SET) - @window_position
end