lib/bindata/io.rb in bindata-1.5.0 vs lib/bindata/io.rb in bindata-1.5.1
- old
+ new
@@ -3,10 +3,13 @@
module BinData
# A wrapper around an IO object. The wrapper provides a consistent
# interface for BinData objects to use when accessing the IO.
class IO
+ # The underlying IO is unseekable
+ class Unseekable < StandardError; end
+
# Creates a StringIO around +str+.
def self.create_string_io(str = "")
if str.respond_to?(:force_encoding)
str = str.dup.force_encoding(Encoding::BINARY)
end
@@ -39,11 +42,11 @@
end
@raw_io = io
# initial stream position if stream supports positioning
- @initial_pos = positioning_supported? ? io.pos : 0
+ @initial_pos = current_position rescue 0
# bits when reading
@rnbits = 0
@rval = 0
@rendian = nil
@@ -58,29 +61,25 @@
attr_reader :raw_io
# Returns the current offset of the io stream. The exact value of
# the offset when reading bitfields is not defined.
def offset
- if positioning_supported?
- @raw_io.pos - @initial_pos
- else
- 0
- end
+ current_position - @initial_pos
+ rescue Unseekable
+ 0
end
# The number of bytes remaining in the input stream.
def num_bytes_remaining
- if positioning_supported?
- pos = @raw_io.pos
- @raw_io.seek(0, ::IO::SEEK_END)
- bytes_remaining = @raw_io.pos - pos
- @raw_io.seek(pos, ::IO::SEEK_SET)
+ pos = current_position
+ @raw_io.seek(0, ::IO::SEEK_END)
+ bytes_remaining = current_position - pos
+ @raw_io.seek(pos, ::IO::SEEK_SET)
- bytes_remaining
- else
- 0
- end
+ bytes_remaining
+ rescue Unseekable
+ 0
end
# Seek +n+ bytes from the current position in the io stream.
def seekbytes(n)
reset_read_bits
@@ -126,11 +125,10 @@
end
# Discards any read bits so the stream becomes aligned at the
# next byte boundary.
def reset_read_bits
- raise "Internal state error nbits = #{@rnbits}" if @rnbits >= 8
@rnbits = 0
@rval = 0
end
# Writes the given string of bytes to the io stream.
@@ -168,19 +166,13 @@
alias_method :flush, :flushbits
#---------------
private
- def positioning_supported?
- unless defined? @positioning_supported
- @positioning_supported = begin
- @raw_io.pos
- true
- rescue NoMethodError, Errno::ESPIPE
- false
- end
- end
- @positioning_supported
+ def current_position
+ @raw_io.pos
+ rescue NoMethodError, Errno::ESPIPE
+ raise Unseekable
end
def skipbytes(n)
# skip over data in 8k blocks
while n > 0