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