Class: Kaitai::Struct::SubIO
- Inherits:
-
Object
- Object
- Kaitai::Struct::SubIO
- Defined in:
- lib/kaitai/struct/struct.rb
Overview
Substream IO implementation: a IO object which wraps existing IO object and provides similar byte/bytes reading functionality, but only for a limited set of bytes starting from specified offset and spanning up to specified length.
Instance Attribute Summary collapse
-
#parent_io ⇒ Object
readonly
Parent IO object that this substream is projecting data from.
-
#parent_start ⇒ Object
readonly
Offset of start of substream in coordinates of parent stream.
-
#pos ⇒ Object
readonly
Current position in a substream.
-
#size ⇒ Object
readonly
Size of substream in bytes.
Instance Method Summary collapse
- #close ⇒ Object
- #closed? ⇒ Boolean
- #eof? ⇒ Boolean
- #getc ⇒ Object
-
#initialize(parent_io, parent_start, size) ⇒ SubIO
constructor
A new instance of SubIO.
- #read(len = nil) ⇒ Object
- #seek(offset, whence = IO::SEEK_SET) ⇒ Object
Constructor Details
#initialize(parent_io, parent_start, size) ⇒ SubIO
Returns a new instance of SubIO.
618 619 620 621 622 623 624 |
# File 'lib/kaitai/struct/struct.rb', line 618 def initialize(parent_io, parent_start, size) @parent_io = parent_io @parent_start = parent_start @size = size @pos = 0 @closed = false end |
Instance Attribute Details
#parent_io ⇒ Object (readonly)
Parent IO object that this substream is projecting data from.
602 603 604 |
# File 'lib/kaitai/struct/struct.rb', line 602 def parent_io @parent_io end |
#parent_start ⇒ Object (readonly)
Offset of start of substream in coordinates of parent stream. In coordinates of substream itself start will be always 0.
607 608 609 |
# File 'lib/kaitai/struct/struct.rb', line 607 def parent_start @parent_start end |
#pos ⇒ Object (readonly)
Current position in a substream. Independent from a position in a parent IO.
616 617 618 |
# File 'lib/kaitai/struct/struct.rb', line 616 def pos @pos end |
#size ⇒ Object (readonly)
Size of substream in bytes.
611 612 613 |
# File 'lib/kaitai/struct/struct.rb', line 611 def size @size end |
Instance Method Details
#close ⇒ Object
701 702 703 704 |
# File 'lib/kaitai/struct/struct.rb', line 701 def close @closed = true nil end |
#closed? ⇒ Boolean
706 707 708 |
# File 'lib/kaitai/struct/struct.rb', line 706 def closed? @closed end |
#eof? ⇒ Boolean
626 627 628 629 630 |
# File 'lib/kaitai/struct/struct.rb', line 626 def eof? raise IOError.new('not opened for reading') if @closed @pos >= @size end |
#getc ⇒ Object
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
# File 'lib/kaitai/struct/struct.rb', line 642 def getc raise IOError.new('not opened for reading') if @closed return nil if @pos >= @size # remember position in parent IO old_pos = @parent_io.pos @parent_io.seek(@parent_start + @pos) begin res = @parent_io.getc @pos += 1 ensure # restore position in parent IO @parent_io.seek(old_pos) end res end |
#read(len = nil) ⇒ Object
661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 |
# File 'lib/kaitai/struct/struct.rb', line 661 def read(len = nil) raise IOError.new('not opened for reading') if @closed # read until the end of substream if len.nil? len = @size - @pos return String.new if len <= 0 elsif len.respond_to?(:to_int) len = len.to_int # special case for requesting exactly 0 bytes return String.new if len == 0 if len > 0 # cap intent to read if going beyond substream boundary left = @size - @pos # if actually requested reading and we're beyond the boundary, return nil return nil if left <= 0 # otherwise, still return something, but less than requested len = left if len > left end end # remember position in parent IO old_pos = @parent_io.pos @parent_io.seek(@parent_start + @pos) begin res = @parent_io.read(len) read_len = res.bytesize @pos += read_len ensure # restore position in parent IO @parent_io.seek(old_pos) end res end |
#seek(offset, whence = IO::SEEK_SET) ⇒ Object
632 633 634 635 636 637 638 639 640 |
# File 'lib/kaitai/struct/struct.rb', line 632 def seek(offset, whence = IO::SEEK_SET) raise ArgumentError.new('only IO::SEEK_SET is supported by SubIO#seek') unless whence == IO::SEEK_SET offset = Internal.num2long(offset) raise IOError.new('closed stream') if @closed raise Errno::EINVAL if offset < 0 @pos = offset.to_int return 0 end |