Class: Omnizip::Formats::Ole::RangesIO
- Inherits:
-
Object
- Object
- Omnizip::Formats::Ole::RangesIO
- Defined in:
- lib/omnizip/formats/ole/ranges_io.rb
Overview
Virtual IO for non-contiguous byte ranges
Provides a contiguous IO interface over scattered byte ranges in an underlying IO object.
Direct Known Subclasses
Instance Attribute Summary collapse
-
#io ⇒ IO
readonly
Underlying IO object.
-
#pos ⇒ Integer
(also: #tell)
Current position.
-
#ranges ⇒ Array<Array<Integer, Integer>>
Byte ranges [[offset, length], ...].
-
#size ⇒ Integer
readonly
Total size in bytes.
Class Method Summary collapse
-
.open(io, ranges = []) {|RangesIO| ... } ⇒ Object
Open with block support.
Instance Method Summary collapse
-
#close ⇒ Object
Close and free resources.
-
#eof? ⇒ Boolean
Check if at end.
-
#free ⇒ void
Free resources to prevent memory leaks.
-
#initialize(io, ranges = []) ⇒ RangesIO
constructor
Initialize RangesIO.
-
#inspect ⇒ Object
Inspect.
-
#read(limit = nil) ⇒ String
Read data.
-
#rewind ⇒ Object
Rewind to beginning.
-
#truncate(_size) ⇒ Object
Truncate (not supported by default).
-
#write(data) ⇒ Integer
(also: #<<)
Write data.
Constructor Details
#initialize(io, ranges = []) ⇒ RangesIO
Initialize RangesIO
27 28 29 30 31 32 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 27 def initialize(io, ranges = []) @io = io @pos = 0 @active = 0 self.ranges = ranges end |
Instance Attribute Details
#io ⇒ IO (readonly)
Returns Underlying IO object.
12 13 14 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 12 def io @io end |
#pos ⇒ Integer Also known as: tell
Returns Current position.
21 22 23 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 21 def pos @pos end |
#ranges ⇒ Array<Array<Integer, Integer>>
Returns Byte ranges [[offset, length], ...].
15 16 17 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 15 def ranges @ranges end |
#size ⇒ Integer (readonly)
Returns Total size in bytes.
18 19 20 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 18 def size @size end |
Class Method Details
.open(io, ranges = []) {|RangesIO| ... } ⇒ Object
Open with block support
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 37 def self.open(io, ranges = []) ranges_io = new(io, ranges) if block_given? begin yield ranges_io ensure ranges_io.close end else ranges_io end end |
Instance Method Details
#close ⇒ Object
Close and free resources
230 231 232 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 230 def close free end |
#eof? ⇒ Boolean
Check if at end
131 132 133 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 131 def eof? @pos == @size end |
#free ⇒ void
This method returns an undefined value.
Free resources to prevent memory leaks
79 80 81 82 83 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 79 def free @io = nil @ranges = nil @offsets = nil end |
#inspect ⇒ Object
Inspect
235 236 237 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 235 def inspect "#<#{self.class} io=#{@io.inspect}, size=#{@size}, pos=#{@pos}>" end |
#read(limit = nil) ⇒ String
Read data
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 139 def read(limit = nil) data = "".b return data if eof? limit ||= @size return data if limit <= 0 range_pos, range_len = @ranges[@active] diff = @pos - @offsets[@active] range_pos += diff range_len -= diff loop do @io.seek(range_pos) if limit < range_len chunk = @io.read(limit).to_s @pos += chunk.length data << chunk break end chunk = @io.read(range_len).to_s @pos += chunk.length data << chunk break if chunk.length != range_len limit -= range_len break if @active >= @ranges.length - 1 @active += 1 range_pos, range_len = @ranges[@active] end data end |
#rewind ⇒ Object
Rewind to beginning
124 125 126 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 124 def rewind seek(0) end |
#truncate(_size) ⇒ Object
Truncate (not supported by default)
225 226 227 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 225 def truncate(_size) raise NotImplementedError, "truncate not supported" end |
#write(data) ⇒ Integer Also known as: <<
Write data
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# File 'lib/omnizip/formats/ole/ranges_io.rb', line 181 def write(data) data = data.dup.force_encoding(Encoding::ASCII_8BIT) if data.is_a?(String) return 0 if data.empty? # Grow if needed if data.length > @size - @pos truncate(@pos + data.length) end range_pos, range_len = @ranges[@active] diff = @pos - @offsets[@active] range_pos += diff range_len -= diff written = 0 loop do @io.seek(range_pos) if written + range_len > data.length chunk = data[written..] @io.write(chunk) @pos += chunk.length break end @io.write(data[written, range_len]) @pos += range_len written += range_len break if @active >= @ranges.length - 1 @active += 1 range_pos, range_len = @ranges[@active] end data.length end |