X-Git-Url: http://nitlanguage.org diff --git a/lib/core/stream.nit b/lib/core/stream.nit index c86ea1b..3fc3f30 100644 --- a/lib/core/stream.nit +++ b/lib/core/stream.nit @@ -215,13 +215,16 @@ abstract class Reader # Reads a String of at most `i` length fun read(i: Int): String do + assert i >= 0 var cs = new CString(i) var rd = read_bytes_to_cstring(cs, i) + if rd < 0 then return "" return codec.decode_string(cs, rd) end # Reads up to `max` bytes from source fun read_bytes(max: Int): Bytes do + assert max >= 0 var cs = new CString(max) var rd = read_bytes_to_cstring(cs, max) return new Bytes(cs, rd, max) @@ -412,7 +415,11 @@ abstract class Reader # Is there something to read. # This function returns 'false' if there is something to read. - fun eof: Bool is abstract + fun eof: Bool do + if lookahead_length > 0 then return false + lookahead_length = raw_read_bytes(lookahead, 1) + return lookahead_length <= 0 + end # Read the next sequence of non whitespace characters. # @@ -592,189 +599,6 @@ redef class Text redef fun write_to(stream) do stream.write(self) end -# Input streams with a buffered input for efficiency purposes -abstract class BufferedReader - super Reader - - redef fun raw_read_byte - do - if last_error != null then return -1 - if eof then - last_error = new IOError("Stream has reached eof") - return -1 - end - var c = _buffer[_buffer_pos] - _buffer_pos += 1 - return c.to_i - end - - # Resets the internal buffer - fun buffer_reset do - _buffer_length = 0 - _buffer_pos = 0 - end - - # Peeks up to `n` bytes in the buffer - # - # The operation does not consume the buffer - # - # ~~~nitish - # var x = new FileReader.open("File.txt") - # assert x.peek(5) == x.read(5) - # ~~~ - fun peek(i: Int): Bytes do - if eof then return new Bytes.empty - var remsp = _buffer_length - _buffer_pos - if i <= remsp then - var bf = new Bytes.with_capacity(i) - bf.append_ns_from(_buffer, i, _buffer_pos) - return bf - end - var bf = new Bytes.with_capacity(i) - bf.append_ns_from(_buffer, remsp, _buffer_pos) - _buffer_pos = _buffer_length - read_intern(i - bf.length, bf) - remsp = _buffer_length - _buffer_pos - var full_len = bf.length + remsp - if full_len > _buffer_capacity then - var c = _buffer_capacity - while c < full_len do c = c * 2 + 2 - _buffer_capacity = c - end - var nns = new CString(_buffer_capacity) - bf.items.copy_to(nns, bf.length, 0, 0) - _buffer.copy_to(nns, remsp, _buffer_pos, bf.length) - _buffer = nns - _buffer_pos = 0 - _buffer_length = full_len - return bf - end - - redef fun read_bytes_to_cstring(buf, i) - do - if last_error != null then return 0 - var bbf = new Bytes(buf, 0, i) - return read_intern(i, bbf) - end - - # Fills `buf` with at most `i` bytes read from `self` - private fun read_intern(i: Int, buf: Bytes): Int do - if eof then return 0 - var p = _buffer_pos - var bufsp = _buffer_length - p - if bufsp >= i then - _buffer_pos += i - buf.append_ns_from(_buffer, i, p) - return i - end - _buffer_pos = _buffer_length - var readln = _buffer_length - p - buf.append_ns_from(_buffer, readln, p) - var rd = read_intern(i - readln, buf) - return rd + readln - end - - redef fun read_all_bytes - do - if last_error != null then return new Bytes.empty - var s = new Bytes.with_capacity(10) - var b = _buffer - while not eof do - var j = _buffer_pos - var k = _buffer_length - var rd_sz = k - j - s.append_ns_from(b, rd_sz, j) - _buffer_pos = k - fill_buffer - end - return s - end - - redef fun append_line_to(s) - do - var lb = new Bytes.with_capacity(10) - loop - # First phase: look for a '\n' - var i = _buffer_pos - while i < _buffer_length and _buffer[i] != 0xAu8 do - i += 1 - end - - var eol - if i < _buffer_length then - assert _buffer[i] == 0xAu8 - i += 1 - eol = true - else - eol = false - end - - # if there is something to append - if i > _buffer_pos then - # Copy from the buffer to the string - var j = _buffer_pos - while j < i do - lb.add(_buffer[j]) - j += 1 - end - _buffer_pos = i - else - assert end_reached - s.append lb.to_s - return - end - - if eol then - # so \n is found - s.append lb.to_s - return - else - # so \n is not found - if end_reached then - s.append lb.to_s - return - end - fill_buffer - end - end - end - - redef fun eof - do - if _buffer_pos < _buffer_length then return false - if end_reached then return true - fill_buffer - return _buffer_pos >= _buffer_length and end_reached - end - - # The buffer - private var buffer: CString = new CString(0) - - # The current position in the buffer - private var buffer_pos = 0 - - # Length of the current buffer (i.e. nuber of bytes in the buffer) - private var buffer_length = 0 - - # Capacity of the buffer - private var buffer_capacity = 0 - - # Fill the buffer - protected fun fill_buffer is abstract - - # Has the last fill_buffer reached the end - protected fun end_reached: Bool is abstract - - # Allocate a `_buffer` for a given `capacity`. - protected fun prepare_buffer(capacity: Int) - do - _buffer = new CString(capacity) - _buffer_pos = 0 # need to read - _buffer_length = 0 - _buffer_capacity = capacity - end -end - # A `Stream` that can be written to and read from abstract class Duplex super Reader