Created
January 25, 2014 16:57
-
-
Save wader/8619462 to your computer and use it in GitHub Desktop.
Sparse ruby IO class
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class SparseFile < IO | |
| def initialize(ranges, total_length, fill = "\0") | |
| @ranges = ranges | |
| @total_length = total_length | |
| @position = 0 | |
| @fill = fill | |
| end | |
| def rewind | |
| @position = 0 | |
| end | |
| # read([length [, outbuf]]) → string, outbuf, or nil | |
| # Reads length bytes from the I/O stream. | |
| def read(length=-1, outbuf=nil) | |
| buf = [] | |
| buf_length = 0 | |
| # rest of file | |
| length = @total_length-@position if length == -1 | |
| length = length - @position if @position+length > @total_length | |
| lenght = 0 if length < 0 | |
| # 01234567890123456789 | |
| # ABCDEF GHIJK | |
| # [ ] before | |
| # [ ] half | |
| # [ ] full | |
| # [ ] combined | |
| # [ ] half | |
| @ranges.each do |offset, buffer| | |
| # to far | |
| if @position+length < offset | |
| break | |
| end | |
| # enough | |
| if length == 0 | |
| break | |
| end | |
| # skip | |
| if offset+buffer.length < @position | |
| next | |
| end | |
| # pad before | |
| if @position < offset | |
| n = offset-@position | |
| buf.push(@fill*n) | |
| length -= n | |
| @position += n | |
| end | |
| o = @position-offset | |
| n = length > buffer.length-o ? buffer.length-o : length | |
| buf.push(buffer[o,n]) | |
| length -= n | |
| @position += n | |
| end | |
| # pad after | |
| buf.push(@fill*(length-buf_length)) if buf_length < length | |
| @position += length | |
| buf.join | |
| end | |
| # seek(amount, whence=IO::SEEK_SET) -> 0 | |
| # Seeks to a given offset anInteger in the stream according to the value of whence: | |
| def seek(amount, whence=IO::SEEK_SET) | |
| @position = case whence | |
| when IO::SEEK_CUR then @position+amount | |
| when IO::SEEK_END then @total_length+amount | |
| when IO::SEEK_SET then amount | |
| end | |
| @position = @total_length if @position > @total_length | |
| @position = 0 if @position < 0 | |
| 0 | |
| end | |
| # def method_missing(m, *args, &block) | |
| # puts "missing", m | |
| # end | |
| end | |
| if false | |
| r = SparseFile.new([ | |
| [5, "abcdef"], | |
| [13, "ghijk"] | |
| ], 20, "-") | |
| expected = [ | |
| "---", | |
| "--ab", | |
| "cde", | |
| "f--gh", | |
| "ijk-" | |
| ] | |
| actual = [ | |
| r.read(3), | |
| r.read(4), | |
| r.read(3), | |
| r.read(5), | |
| r.read(4) | |
| ] | |
| puts | |
| puts expected | |
| puts | |
| puts actual | |
| puts | |
| r.rewind | |
| puts r.read(20) | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment