Class | CSV::StreamBuf |
In: |
lib/csv.rb
|
Parent: | Object |
Buffered stream.
EXAMPLE 1 — an IO.
class MyBuf < StreamBuf # Do initialize myself before a super class. Super class might call my # method 'read'. (Could be awful for C++ user. :-) def initialize(s) @s = s super() end # define my own 'read' method. # CAUTION: Returning nil means EnfOfStream. def read(size) @s.read(size) end # release buffers. in Ruby which has GC, you do not have to call this... def terminate @s = nil super() end end buf = MyBuf.new(STDIN) my_str = '' p buf[0, 0] # => '' (null string) p buf[0] # => 97 (char code of 'a') p buf[0, 1] # => 'a' my_str = buf[0, 5] p my_str # => 'abcde' (5 chars) p buf[0, 6] # => "abcde\n" (6 chars) p buf[0, 7] # => "abcde\n" (6 chars) p buf.drop(3) # => 3 (dropped chars) p buf.get(0, 2) # => 'de' (2 chars) p buf.is_eos? # => false (is not EOS here) p buf.drop(5) # => 3 (dropped chars) p buf.is_eos? # => true (is EOS here) p buf[0] # => nil (is EOS here)
EXAMPLE 2 — String.
This is a conceptual example. No pros with this. class StrBuf < StreamBuf def initialize(s) @str = s @idx = 0 super() end def read(size) str = @str[@idx, size] @idx += str.size str end end
BufSize | = | 1024 * 8 |
WARN: Do not instantiate this class directly. Define your own class which derives this class and define ‘read’ instance method.
# File lib/csv.rb, line 888 888: def initialize 889: @buf_list = [] 890: @cur_buf = @buf_tail_idx = -1 891: @offset = 0 892: @is_eos = false 893: add_buf 894: @cur_buf = @buf_tail_idx 895: end
get a char or a partial string from the stream. idx: index of a string to specify a start point of a string to get. unlike String instance, idx < 0 returns nil. n: size of a string to get. returns char at idx if n == nil. returns a partial string, from idx to (idx + n) if n != nil. at EOF, the string size could not equal to arg n.
# File lib/csv.rb, line 803 803: def [](idx, n = nil) 804: if idx < 0 805: return nil 806: end 807: if (idx_is_eos?(idx)) 808: if n and (@offset + idx == buf_size(@cur_buf)) 809: # Like a String, 'abc'[4, 1] returns nil and 810: # 'abc'[3, 1] returns '' not nil. 811: return '' 812: else 813: return nil 814: end 815: end 816: my_buf = @cur_buf 817: my_offset = @offset 818: next_idx = idx 819: while (my_offset + next_idx >= buf_size(my_buf)) 820: if (my_buf == @buf_tail_idx) 821: unless add_buf 822: break 823: end 824: end 825: next_idx = my_offset + next_idx - buf_size(my_buf) 826: my_buf += 1 827: my_offset = 0 828: end 829: loc = my_offset + next_idx 830: if !n 831: return @buf_list[my_buf][loc] # Fixnum of char code. 832: elsif (loc + n - 1 < buf_size(my_buf)) 833: return @buf_list[my_buf][loc, n] # String. 834: else # should do loop insted of (tail) recursive call... 835: res = @buf_list[my_buf][loc, BufSize] 836: size_added = buf_size(my_buf) - loc 837: if size_added > 0 838: idx += size_added 839: n -= size_added 840: ret = self[idx, n] 841: if ret 842: res << ret 843: end 844: end 845: return res 846: end 847: end
drop a string from the stream. returns dropped size. at EOF, dropped size might not equals to arg n. Once you drop the head of the stream, access to the dropped part via [] or get returns nil.
# File lib/csv.rb, line 854 854: def drop(n) 855: if is_eos? 856: return 0 857: end 858: size_dropped = 0 859: while (n > 0) 860: if !@is_eos or (@cur_buf != @buf_tail_idx) 861: if (@offset + n < buf_size(@cur_buf)) 862: size_dropped += n 863: @offset += n 864: n = 0 865: else 866: size = buf_size(@cur_buf) - @offset 867: size_dropped += size 868: n -= size 869: @offset = 0 870: unless rel_buf 871: unless add_buf 872: break 873: end 874: @cur_buf = @buf_tail_idx 875: end 876: end 877: end 878: end 879: size_dropped 880: end
protected method ‘read’ must be defined in derived classes. CAUTION: Returning a string which size is not equal to ‘size’ means EnfOfStream. When it is not at EOS, you must block the callee, try to read and return the sized string.
# File lib/csv.rb, line 907 907: def read(size) # raise EOFError 908: raise NotImplementedError.new('Method read must be defined in a derived class.') 909: end
# File lib/csv.rb, line 917 917: def add_buf 918: if @is_eos 919: return false 920: end 921: begin 922: str_read = read(BufSize) 923: rescue EOFError 924: str_read = nil 925: rescue 926: terminate 927: raise 928: end 929: if str_read.nil? 930: @is_eos = true 931: @buf_list.push('') 932: @buf_tail_idx += 1 933: false 934: else 935: @buf_list.push(str_read) 936: @buf_tail_idx += 1 937: true 938: end 939: end