| 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