module io::push_back_reader
# Input stream that permits to push bytes back to the stream.
-interface PushBackReader
+class PushBackReader
super IStream
# Push the specified byte back to the stream.
if (pipeflag & 1) {
int res = pipe(in_fd);
if ( res == -1 ) {
- fprintf( stderr, "Pipe init failed in Process:basic_exec_execute: %s\n", strerror( errno ) );
- exit(1);
+ return NULL;
}
}
if (pipeflag & 2) {
int res = pipe(out_fd);
if ( res == -1 ) {
- fprintf( stderr, "Pipe init failed in Process:basic_exec_execute: %s\n", strerror( errno ) );
- exit(1);
+ return NULL;
}
}
if (pipeflag & 4) {
int res = pipe(err_fd);
if ( res == -1 ) {
- fprintf( stderr, "Pipe init failed in Process:basic_exec_execute: %s\n", strerror( errno ) );
- exit(1);
+ return NULL;
}
}
# The original path is reused, therefore the reopened file can be a different file.
fun reopen
do
- if not eof then close
+ if not eof and not _file.address_is_null then close
+ last_error = null
_file = new NativeFile.io_open_read(path.to_cstring)
+ if _file.address_is_null then
+ last_error = new IOError("Error: Opening file at '{path.as(not null)}' failed with '{sys.errno.strerror}'")
+ end_reached = true
+ return
+ end
end_reached = false
_buffer_pos = 0
_buffer.clear
redef fun close
do
+ if _file.address_is_null then return
var i = _file.io_close
_buffer.clear
end_reached = true
_buffer.length = nb
_buffer_pos = 0
end
-
+
# End of file?
redef var end_reached: Bool = false
self.path = path
prepare_buffer(10)
_file = new NativeFile.io_open_read(path.to_cstring)
- assert not _file.address_is_null else
- print "Error: Opening file at '{path}' failed with '{sys.errno.strerror}'"
+ if _file.address_is_null then
+ last_error = new IOError("Error: Opening file at '{path}' failed with '{sys.errno.strerror}'")
+ end_reached = true
end
end
redef fun write(s)
do
- assert _is_writable
+ if last_error != null then return
+ if not _is_writable then
+ last_error = new IOError("Cannot write to non-writable stream")
+ return
+ end
if s isa FlatText then
write_native(s.to_cstring, s.length)
else
redef fun close
do
+ if _file.address_is_null then
+ if last_error != null then return
+ last_error = new IOError("Cannot close unopened write stream")
+ _is_writable = false
+ return
+ end
var i = _file.io_close
+ if i != 0 then
+ last_error = new IOError("Close failed due to error {sys.errno.strerror}")
+ end
_is_writable = false
end
-
redef var is_writable = false
# Write `len` bytes from `native`.
private fun write_native(native: NativeString, len: Int)
do
- assert _is_writable
+ if last_error != null then return
+ if not _is_writable then
+ last_error = new IOError("Cannot write to non-writable stream")
+ return
+ end
+ if _file.address_is_null then
+ last_error = new IOError("Writing on a null stream")
+ _is_writable = false
+ return
+ end
var err = _file.io_write(native, len)
if err != len then
# Big problem
- printn("Problem in writing : ", err, " ", len, "\n")
+ last_error = new IOError("Problem in writing : {err} {len} \n")
end
end
init open(path: String)
do
_file = new NativeFile.io_open_write(path.to_cstring)
- assert not _file.address_is_null else
- print "Error: Opening file at '{path}' failed with '{sys.errno.strerror}'"
- end
self.path = path
_is_writable = true
+ if _file.address_is_null then
+ last_error = new IOError("Error: Opening file at '{path}' failed with '{sys.errno.strerror}'")
+ is_writable = false
+ end
end
end
module stream
intrude import ropes
+import error
in "C" `{
#include <unistd.h>
#include <signal.h>
`}
+# Any kind of error that could be produced by an operation on Streams
+class IOError
+ super Error
+end
+
# Abstract stream class
-interface IOS
+abstract class IOS
+ # Error produced by the file stream
+ #
+ # var ifs = new IFStream.open("donotmakethisfile.binx")
+ # ifs.read_all
+ # ifs.close
+ # assert ifs.last_error != null
+ var last_error: nullable IOError = null
+
# close the stream
fun close is abstract
end
# Abstract input streams
-interface IStream
+abstract class IStream
super IOS
# Read a character. Return its ASCII value, -1 on EOF or timeout
fun read_char: Int is abstract
# Read at most i bytes
fun read(i: Int): String
do
+ if last_error != null then return ""
var s = new FlatBuffer.with_capacity(i)
while i > 0 and not eof do
var c = read_char
# Read a string until the end of the line.
fun read_line: String
do
+ if last_error != null then return ""
assert not eof
var s = new FlatBuffer
append_line_to(s)
# Read all the stream until the eof.
fun read_all: String
do
+ if last_error != null then return ""
var s = new FlatBuffer
while not eof do
var c = read_char
# Read a string until the end of the line and append it to `s`.
fun append_line_to(s: Buffer)
do
+ if last_error != null then return
loop
var x = read_char
if x == -1 then
end
# IStream capable of declaring if readable without blocking
-interface PollableIStream
+abstract class PollableIStream
super IStream
# Is there something to read? (without blocking)
end
# Abstract output stream
-interface OStream
+abstract class OStream
super IOS
# write a string
fun write(s: Text) is abstract
super IStream
redef fun read_char
do
- assert not eof
+ if last_error != null then return 0
+ if eof then last_error = new IOError("Stream has reached eof")
if _buffer_pos >= _buffer.length then
fill_buffer
end
redef fun read(i)
do
+ if last_error != null then return ""
if _buffer.length == _buffer_pos then
if not eof then
fill_buffer
redef fun read_all
do
+ if last_error != null then return ""
var s = new FlatBuffer
while not eof do
var j = _buffer_pos
end
end
-interface IOStream
+abstract class IOStream
super IStream
super OStream
end
--- /dev/null
+Error: Opening file at 'donotcreate.bing' failed with 'No such file or directory'
+Error: Opening file at 'donotcreate.bing' failed with 'No such file or directory'
--- /dev/null
+# 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 ifs = new IFStream.open("donotcreate.bing")
+
+var s = ifs.read_all
+
+ifs.close
+
+if ifs.last_error != null then print ifs.last_error.as(not null)
+
+ifs.reopen
+
+s = ifs.read_all
+
+ifs.close
+
+if ifs.last_error != null then print ifs.last_error.as(not null)