From: Lucas Bajolet Date: Tue, 12 May 2015 15:42:25 +0000 (-0400) Subject: lib/standard: Removed push_back_reader and replaced it by a peek operation on Buffere... X-Git-Tag: v0.7.5~56^2 X-Git-Url: http://nitlanguage.org lib/standard: Removed push_back_reader and replaced it by a peek operation on BufferedReaders Signed-off-by: Lucas Bajolet --- diff --git a/lib/io/io.nit b/lib/io/io.nit deleted file mode 100644 index c48b171..0000000 --- a/lib/io/io.nit +++ /dev/null @@ -1,14 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# This file is free software, which comes along with NIT. This software is -# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. You can modify it is you want, provided this header -# is kept unaltered, and a notification of the changes is added. -# You are allowed to redistribute it and sell it, alone or is a part of -# another product. - -# Additional services for streams. -module io - -import push_back_reader diff --git a/lib/io/push_back_reader.nit b/lib/io/push_back_reader.nit deleted file mode 100644 index 2fa2d19..0000000 --- a/lib/io/push_back_reader.nit +++ /dev/null @@ -1,110 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# This file is free software, which comes along with NIT. This software is -# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. You can modify it is you want, provided this header -# is kept unaltered, and a notification of the changes is added. -# You are allowed to redistribute it and sell it, alone or is a part of -# another product. - -# Input stream that permits to push bytes back to the stream. -module io::push_back_reader - -# Input stream that permits to push bytes back to the stream. -class PushBackReader - super Reader - - # Push the specified byte back to the stream. - # - # The specified byte is usually the last read byte that is not - # “unread” already. - fun unread_char(c: Char) is abstract - - # Push the specified string back to the stream. - # - # The specified string is usually the last read string that is not - # “unread” already. - fun unread(s: String) do - for c in s.chars.reverse_iterator do unread_char(c) - end -end - -# Decorates an input stream to permit to push bytes back to the input stream. -class PushBackDecorator - super PushBackReader - - # The parent stream. - var parent: Reader - - # The stack of the pushed-back bytes. - # - # Bytes are in the reverse order they will reappear in the stream. - # `unread` pushes bytes after already pushed-back bytes. - # - # TODO: With optimized bulk array copy operations, a reversed stack (like in - # OpenJDK) would be more efficient. - private var buf: Sequence[Char] = new Array[Char] - - redef fun read_char: Int do - if buf.length <= 0 then return parent.read_char - return buf.pop.ascii - end - - redef fun read(i: Int): String do - if i <= 0 then return "" - if buf.length <= 0 then return parent.read(i) - var s = new FlatBuffer.with_capacity(i) - - loop - s.chars.push(buf.pop) - i -= 1 - if i <= 0 then - return s.to_s - else if buf.length <= 0 then - s.append(parent.read(i)) - return s.to_s - end - end - end - - redef fun read_all: String do - if buf.length <= 0 then return parent.read_all - var s = new FlatBuffer - - loop - s.chars.push(buf.pop) - if buf.length <= 0 then - s.append(parent.read_all) - return s.to_s - end - end - end - - redef fun append_line_to(s: Buffer) do - if buf.length > 0 then - var c: Char - - loop - c = buf.pop - s.chars.push(c) - if c == '\n' then return - if buf.length <= 0 then break - end - end - parent.append_line_to(s) - end - - redef fun eof: Bool do return buf.length <= 0 and parent.eof - - redef fun close do - buf.clear - parent.close - end - - redef fun unread_char(c: Char) do buf.push(c) - - redef fun unread(s: String) do - for c in s.chars.reverse_iterator do buf.push(c) - end -end diff --git a/lib/io/test_push_back_reader.nit b/lib/io/test_push_back_reader.nit deleted file mode 100644 index 1498ccf..0000000 --- a/lib/io/test_push_back_reader.nit +++ /dev/null @@ -1,158 +0,0 @@ -# This file is part of NIT ( http://www.nitlanguage.org ). -# -# This file is free software, which comes along with NIT. This software is -# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; -# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -# PARTICULAR PURPOSE. You can modify it is you want, provided this header -# is kept unaltered, and a notification of the changes is added. -# You are allowed to redistribute it and sell it, alone or is a part of -# another product. - -# Test suites for module `push_back_reader` -module test_push_back_reader is test_suite - -import test_suite -import io::push_back_reader - -class TestPushBackDecorator - super TestSuite - - private fun sample: PushBackDecorator do - return new PushBackDecorator(new StringReader(""" -abcd - -efg -""")) - end - - fun test_read_char do - var subject = sample - - assert 'a' == subject.read_char.ascii - end - - fun test_read_char_eof do - var subject = new PushBackDecorator(new StringReader("")) - - assert -1 == subject.read_char - end - - fun test_unread_read_char do - var subject = sample - - subject.unread_char('z') - assert 'z' == subject.read_char.ascii - assert 'a' == subject.read_char.ascii - end - - fun test_read_partial do - var subject = sample - - assert "abcd" == subject.read(4) - end - - fun test_read_too_much do - var subject = sample - var exp = """ -abcd - -efg -""" - assert exp == subject.read(100) - end - - fun test_unread_read do - var subject = sample - - subject.unread("a") - assert "aab" == subject.read(3) - end - - fun test_unread_read_mixed do - var subject = sample - - subject.unread("a") - assert "aab" == subject.read(3) - end - - fun test_read_all do - var subject = sample - var exp = """ -abcd - -efg -""" - assert exp == subject.read_all - end - - fun test_unread_read_all do - var subject = sample - var exp = """ -fooabcd - -efg -""" - subject.unread("foo") - assert exp == subject.read_all - end - - fun test_read_line do - var subject = sample - - assert "abcd" == subject.read_line - assert "" == subject.read_line - end - - fun test_unread_read_line do - var subject = sample - - subject.unread("a\nb") - assert "a" == subject.read_line - assert "babcd" == subject.read_line - end - - fun test_eof do - var subject = sample - - assert not subject.eof - subject.read_all - assert subject.eof - end - - fun test_eof_empty do - var subject = new PushBackDecorator(new StringReader("")) - - assert subject.eof - end - - fun test_close do - var subject = sample - - subject.close - assert subject.eof - end - - fun test_unread_close do - var subject = sample - - subject.unread("foo") - subject.close - assert subject.eof - end - - fun test_unread_char_order do - var subject = sample - - subject.unread_char('z') - subject.unread_char('y') - assert "yzab" == subject.read(4) - end - - fun test_unread_order do - var subject = sample - - subject.unread("bar") - subject.unread("foo") - assert "foobarab" == subject.read(8) - end -end diff --git a/lib/standard/stream.nit b/lib/standard/stream.nit index e0d3a67..4ad6af1 100644 --- a/lib/standard/stream.nit +++ b/lib/standard/stream.nit @@ -392,6 +392,34 @@ abstract class BufferedReader return c.ascii end + # Peeks up to `n` bytes in the buffer, returns an empty string on EOF + # + # The operation does not consume the buffer + # + # ~~~nitish + # var x = new FileReader("File.txt") + # assert x.peek(5) == x.read(5) + # ~~~ + fun peek(i: Int): String do + if eof then return "" + var b = new FlatBuffer.with_capacity(i) + while i > 0 and not eof do + b.add _buffer[_buffer_pos] + _buffer_pos += 1 + i -= 1 + end + var nbuflen = b.length + (_buffer.length - _buffer_pos) + var nbuf = new FlatBuffer.with_capacity(nbuflen) + nbuf.append(b) + while _buffer_pos < _buffer.length do + nbuf.add(_buffer[_buffer_pos]) + _buffer_pos += 1 + end + _buffer_pos = 0 + _buffer = nbuf + return b.to_s + end + redef fun read(i) do if last_error != null then return "" diff --git a/tests/sav/test_peek.res b/tests/sav/test_peek.res new file mode 100644 index 0000000..edc1121 --- /dev/null +++ b/tests/sav/test_peek.res @@ -0,0 +1,33 @@ +# Thi +# Thi +s file is pa +s file is pa +rt of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +var f = new FileReader.open("test_peek.nit") + +print f.peek(5) +print f.read(5) + +print f.peek(12) +print f.read(12) + +print f.read_all + +print f.peek(2) + +f.close + + diff --git a/tests/test_peek.nit b/tests/test_peek.nit new file mode 100644 index 0000000..4c1d433 --- /dev/null +++ b/tests/test_peek.nit @@ -0,0 +1,27 @@ +# This file is part of NIT ( http://www.nitlanguage.org ). +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +var f = new FileReader.open("test_peek.nit") + +print f.peek(5) +print f.read(5) + +print f.peek(12) +print f.read(12) + +print f.read_all + +print f.peek(2) + +f.close