Class: Parsby::BackedIO
- Inherits:
-
Object
- Object
- Parsby::BackedIO
- Defined in:
- lib/parsby.rb
Class Method Summary collapse
-
.for(io, &b) ⇒ Object
Makes a new BackedIO out of the provided IO, calls the provided blocked and restores the IO on an exception.
-
.peek(io, &b) ⇒ Object
Similar to BackedIO.for, but it always restores the IO, even when there’s no exception.
Instance Method Summary collapse
- #col ⇒ Object
-
#current_line ⇒ Object
Returns current line, including what’s to come from #read, without consuming input.
-
#current_line_pos ⇒ Object
pos == current_line_pos + col.
- #current_line_range ⇒ Object
-
#initialize(io) ⇒ BackedIO
constructor
Initializes a BackedIO out of the provided IO object or String.
-
#line_number ⇒ Object
Returns line number of current line.
- #lines_read ⇒ Object
- #load_rest_of_line ⇒ Object
-
#method_missing(m, *args, &b) ⇒ Object
This is to provide transparent delegation to methods of underlying IO.
-
#peek(*args) ⇒ Object
Like #read, but without consuming.
-
#pos ⇒ Object
Delegates pos to inner io, and works around pipes’ inability to return pos by getting the length of the innermost BackedIO.
-
#read(*args) ⇒ Object
Reads from underlying IO and backs it up.
- #readline(*args) ⇒ Object
-
#restore(n = backup.back_size) ⇒ Object
Restore n chars from the backup.
- #restore_to(prev_pos) ⇒ Object
- #seek(amount, whence = IO::SEEK_SET) ⇒ Object
-
#ungetc(c) ⇒ Object
Pass to underlying IO’s ungetc and discard a part of the same length from the backup.
- #with_saved_pos(&b) ⇒ Object
Constructor Details
#initialize(io) ⇒ BackedIO
Initializes a BackedIO out of the provided IO object or String. The String will be turned into an IO using StringIO.
451 452 453 454 455 |
# File 'lib/parsby.rb', line 451 def initialize(io) io = StringIO.new io if io.is_a? String @io = io @backup = Backup.new end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(m, *args, &b) ⇒ Object
This is to provide transparent delegation to methods of underlying IO.
575 576 577 |
# File 'lib/parsby.rb', line 575 def method_missing(m, *args, &b) @io.send(m, *args, &b) end |
Class Method Details
.for(io, &b) ⇒ Object
Makes a new BackedIO out of the provided IO, calls the provided blocked and restores the IO on an exception.
459 460 461 462 463 464 465 466 467 |
# File 'lib/parsby.rb', line 459 def self.for(io, &b) bio = new io begin b.call bio rescue bio.restore raise end end |
.peek(io, &b) ⇒ Object
Similar to BackedIO.for, but it always restores the IO, even when there’s no exception.
471 472 473 474 475 476 477 478 479 |
# File 'lib/parsby.rb', line 471 def self.peek(io, &b) self.for io do |bio| begin b.call bio ensure bio.restore end end end |
Instance Method Details
#col ⇒ Object
533 534 535 |
# File 'lib/parsby.rb', line 533 def col backup.col end |
#current_line ⇒ Object
Returns current line, including what’s to come from #read, without consuming input.
553 554 555 556 |
# File 'lib/parsby.rb', line 553 def current_line load_rest_of_line backup.current_line end |
#current_line_pos ⇒ Object
pos == current_line_pos + col. This is needed to convert a pos to a col.
529 530 531 |
# File 'lib/parsby.rb', line 529 def current_line_pos pos - col end |
#current_line_range ⇒ Object
537 538 539 540 |
# File 'lib/parsby.rb', line 537 def current_line_range start = current_line_pos PosRange.new start, start + current_line.length end |
#line_number ⇒ Object
Returns line number of current line. This is 1-indexed.
504 505 506 |
# File 'lib/parsby.rb', line 504 def line_number lines_read.length end |
#lines_read ⇒ Object
546 547 548 549 |
# File 'lib/parsby.rb', line 546 def lines_read load_rest_of_line backup.back_lines.map(&:chomp) end |
#load_rest_of_line ⇒ Object
542 543 544 |
# File 'lib/parsby.rb', line 542 def load_rest_of_line with_saved_pos { readline } end |
#peek(*args) ⇒ Object
Like #read, but without consuming.
491 492 493 |
# File 'lib/parsby.rb', line 491 def peek(*args) with_saved_pos { read(*args) } end |
#pos ⇒ Object
Delegates pos to inner io, and works around pipes’ inability to return pos by getting the length of the innermost BackedIO.
497 498 499 500 501 |
# File 'lib/parsby.rb', line 497 def pos @io.pos rescue Errno::ESPIPE backup.pos end |
#read(*args) ⇒ Object
Reads from underlying IO and backs it up.
584 585 586 |
# File 'lib/parsby.rb', line 584 def read(*args) @io.read(*args).tap {|r| backup.write r unless r.nil? } end |
#readline(*args) ⇒ Object
579 580 581 |
# File 'lib/parsby.rb', line 579 def readline(*args) @io.readline(*args).tap {|r| backup.write r unless r.nil? } end |
#restore(n = backup.back_size) ⇒ Object
Restore n chars from the backup.
559 560 561 562 563 564 565 566 567 |
# File 'lib/parsby.rb', line 559 def restore(n = backup.back_size) # Handle negatives in consideration of #with_saved_pos. if n < 0 read(-n) else backup.back(n).chars.reverse.each {|c| ungetc c} end nil end |
#restore_to(prev_pos) ⇒ Object
569 570 571 |
# File 'lib/parsby.rb', line 569 def restore_to(prev_pos) restore(pos - prev_pos) end |
#seek(amount, whence = IO::SEEK_SET) ⇒ Object
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 |
# File 'lib/parsby.rb', line 508 def seek(amount, whence = IO::SEEK_SET) if whence == IO::SEEK_END read restore(-amount) return end new_pos = case whence when IO::SEEK_SET amount when IO::SEEK_CUR pos + amount end if new_pos > pos read new_pos - pos else restore_to new_pos end end |
#ungetc(c) ⇒ Object
Pass to underlying IO’s ungetc and discard a part of the same length from the backup. As specified with different IO classes, the argument should be a single character. To restore from the backup, use #restore.
592 593 594 595 596 597 598 |
# File 'lib/parsby.rb', line 592 def ungetc(c) # Though c is supposed to be a single character, as specified by the # ungetc of different IO objects, let's not assume that when # adjusting the backup. backup.seek(-c.length, IO::SEEK_CUR) @io.ungetc(c) end |
#with_saved_pos(&b) ⇒ Object
481 482 483 484 485 486 487 488 |
# File 'lib/parsby.rb', line 481 def with_saved_pos(&b) saved = pos begin b.call saved ensure restore_to saved end end |