Class: IOWindow

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

Overview

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

NOTE: This object is NOT thread safe.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(io, window_position, window_size) ⇒ IOWindow

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

io 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.



19
20
21
22
23
24
# File 'lib/archive/support/iowindow.rb', line 19

def initialize(io, window_position, window_size)
  @io = io
  @unbuffered_pos = 0
  self.window_position = window_position
  self.window_size = window_size
end

Instance Attribute Details

#window_positionObject

The file position at which this window begins.



27
28
29
# File 'lib/archive/support/iowindow.rb', line 27

def window_position
  @window_position
end

#window_sizeObject

The size of the window.



44
45
46
# File 'lib/archive/support/iowindow.rb', line 44

def window_size
  @window_size
end

Instance Method Details

#restore_delegateObject (private)

Restores the state of the delegate IO object to that saved by a prior call to #restore_self.



102
103
104
105
# File 'lib/archive/support/iowindow.rb', line 102

def restore_delegate
  @io.pos = @delegate_pos
  @io.lineno = @delegate_lineno
end

#restore_selfObject (private)

Saves the state of the delegate IO object so that it can be restored later using #restore_delegate and then configures the delegate so as to restore the state of this object.



110
111
112
113
114
# File 'lib/archive/support/iowindow.rb', line 110

def restore_self
  @delegate_pos = @io.pos
  @delegate_lineno = @io.lineno
  @io.pos = @window_position + @unbuffered_pos
end

#unbuffered_read(length) ⇒ Object (private)



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/archive/support/iowindow.rb', line 60

def unbuffered_read(length)
  restore_self

  # Error out if the end of the window is reached.
  raise EOFError, 'end of file reached' if @unbuffered_pos >= @window_size

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

  # Fill a buffer with the data from the delegate.
  buffer = @io.read(length)
  # Error out if the end of the delegate is reached.
  raise EOFError, 'end of file reached' if buffer.nil?

  # Update the position.
  @unbuffered_pos += buffer.length

  buffer
ensure
  restore_delegate
end

#unbuffered_seek(offset, whence = IO::SEEK_SET) ⇒ Object (private)

Raises:

  • (Errno::EINVAL)


82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/archive/support/iowindow.rb', line 82

def unbuffered_seek(offset, whence = IO::SEEK_SET)
  # Convert the offset and whence into an absolute position.
  case whence
  when IO::SEEK_SET
    new_pos = offset
  when IO::SEEK_CUR
    new_pos = @unbuffered_pos + offset
  when IO::SEEK_END
    new_pos = @window_size + offset
  end

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

  # Set the new position.
  @unbuffered_pos = new_pos
end