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
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.
551 552 553 |
# File 'lib/parsby.rb', line 551 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.
435 436 437 438 439 440 441 442 443 |
# File 'lib/parsby.rb', line 435 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.
447 448 449 450 451 452 453 454 455 |
# File 'lib/parsby.rb', line 447 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
509 510 511 |
# File 'lib/parsby.rb', line 509 def col backup.col end |
#current_line ⇒ Object
Returns current line, including what’s to come from #read, without consuming input.
529 530 531 532 |
# File 'lib/parsby.rb', line 529 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.
505 506 507 |
# File 'lib/parsby.rb', line 505 def current_line_pos pos - col end |
#current_line_range ⇒ Object
513 514 515 516 |
# File 'lib/parsby.rb', line 513 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.
480 481 482 |
# File 'lib/parsby.rb', line 480 def line_number lines_read.length end |
#lines_read ⇒ Object
522 523 524 525 |
# File 'lib/parsby.rb', line 522 def lines_read load_rest_of_line backup.back_lines.map(&:chomp) end |
#load_rest_of_line ⇒ Object
518 519 520 |
# File 'lib/parsby.rb', line 518 def load_rest_of_line with_saved_pos { readline } end |
#peek(*args) ⇒ Object
Like #read, but without consuming.
467 468 469 |
# File 'lib/parsby.rb', line 467 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.
473 474 475 476 477 |
# File 'lib/parsby.rb', line 473 def pos @io.pos rescue Errno::ESPIPE backup.pos end |
#read(*args) ⇒ Object
Reads from underlying IO and backs it up.
560 561 562 |
# File 'lib/parsby.rb', line 560 def read(*args) @io.read(*args).tap {|r| backup.write r unless r.nil? } end |
#readline(*args) ⇒ Object
555 556 557 |
# File 'lib/parsby.rb', line 555 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.
535 536 537 538 539 540 541 542 543 |
# File 'lib/parsby.rb', line 535 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
545 546 547 |
# File 'lib/parsby.rb', line 545 def restore_to(prev_pos) restore(pos - prev_pos) end |
#seek(amount, whence = IO::SEEK_SET) ⇒ Object
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 |
# File 'lib/parsby.rb', line 484 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.
568 569 570 571 572 573 574 |
# File 'lib/parsby.rb', line 568 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
457 458 459 460 461 462 463 464 |
# File 'lib/parsby.rb', line 457 def with_saved_pos(&b) saved = pos begin b.call saved ensure restore_to saved end end |