1.1 --- a/lib/__builtins__/file.py Thu Dec 08 19:29:12 2016 +0100
1.2 +++ b/lib/__builtins__/file.py Thu Dec 08 21:45:09 2016 +0100
1.3 @@ -19,14 +19,65 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -class file(object):
1.8 +from __builtins__.types import check_int, check_string
1.9 +import native
1.10 +
1.11 +class filestream:
1.12 +
1.13 + "Generic file-oriented stream functionality."
1.14 +
1.15 + def __init__(self, bufsize=1024):
1.16 + self.bufsize = bufsize
1.17 +
1.18 + def read(self, n=0):
1.19 +
1.20 + "Read 'n' bytes from the stream."
1.21 +
1.22 + check_int(n)
1.23 +
1.24 + # Read any indicated number of bytes.
1.25 +
1.26 + if n > 0:
1.27 + return native._fread(self.__data__, n)
1.28 +
1.29 + # Read all remaining bytes.
1.30 +
1.31 + else:
1.32 + l = []
1.33 +
1.34 + # Read until end-of-file.
1.35 +
1.36 + try:
1.37 + while True:
1.38 + l.append(native._fread(self.__data__, self.bufsize))
1.39 +
1.40 + # Handle end-of-file reads.
1.41 +
1.42 + except EOFError:
1.43 + pass
1.44 +
1.45 + return "".join(l)
1.46 +
1.47 + def write(self, s):
1.48 +
1.49 + "Write string 's' to the stream."
1.50 +
1.51 + check_string(s)
1.52 + native._fwrite(self.__data__, s)
1.53 +
1.54 + def close(self): pass
1.55 +
1.56 +class file(filestream):
1.57
1.58 "A file abstraction."
1.59
1.60 - def __init__(self, name, mode=None, buffering=None): pass
1.61 - def read(self, n=None): pass
1.62 - def write(self, s): pass
1.63 - def close(self): pass
1.64 + def __init__(self, filename, mode="r", bufsize=1024):
1.65 +
1.66 + "Open the file with the given 'filename' using the given access 'mode'."
1.67 +
1.68 + get_using(filestream.__init__, self)(bufsize)
1.69 + self.__data__ = native._fopen(filename, mode)
1.70 +
1.71 def readline(self, size=None): pass
1.72 def readlines(self, size=None): pass
1.73
2.1 --- a/lib/__builtins__/io.py Thu Dec 08 19:29:12 2016 +0100
2.2 +++ b/lib/__builtins__/io.py Thu Dec 08 21:45:09 2016 +0100
2.3 @@ -19,14 +19,7 @@
2.4 this program. If not, see <http://www.gnu.org/licenses/>.
2.5 """
2.6
2.7 -def open(name, mode=None, buffering=None):
2.8 -
2.9 - """
2.10 - Open the file with the given 'name', using the given 'mode' and applying the
2.11 - indicated 'buffering'.
2.12 - """
2.13 -
2.14 - return file(name, mode, buffering)
2.15 +open = file
2.16
2.17 def raw_input(prompt=None): pass
2.18
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/lib/__builtins__/types.py Thu Dec 08 21:45:09 2016 +0100
3.3 @@ -0,0 +1,38 @@
3.4 +#!/usr/bin/env python
3.5 +
3.6 +"""
3.7 +Common type validation functions.
3.8 +
3.9 +Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
3.10 +
3.11 +This program is free software; you can redistribute it and/or modify it under
3.12 +the terms of the GNU General Public License as published by the Free Software
3.13 +Foundation; either version 3 of the License, or (at your option) any later
3.14 +version.
3.15 +
3.16 +This program is distributed in the hope that it will be useful, but WITHOUT
3.17 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3.18 +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
3.19 +details.
3.20 +
3.21 +You should have received a copy of the GNU General Public License along with
3.22 +this program. If not, see <http://www.gnu.org/licenses/>.
3.23 +"""
3.24 +
3.25 +import native
3.26 +
3.27 +def check_int(i):
3.28 +
3.29 + "Check the given int 'i'."
3.30 +
3.31 + if not native._isinstance(i, int):
3.32 + raise ValueError(i)
3.33 +
3.34 +def check_string(s):
3.35 +
3.36 + "Check the given string 's'."
3.37 +
3.38 + if not native._isinstance(s, string):
3.39 + raise ValueError(s)
3.40 +
3.41 +# vim: tabstop=4 expandtab shiftwidth=4
4.1 --- a/lib/native.py Thu Dec 08 19:29:12 2016 +0100
4.2 +++ b/lib/native.py Thu Dec 08 21:45:09 2016 +0100
4.3 @@ -100,6 +100,7 @@
4.4
4.5 # Input/output.
4.6
4.7 +def _fopen(filename, mode): IOError
4.8 def _fdopen(fd, mode): IOError
4.9 def _read(fd, n): IOError
4.10 def _write(fd, str): pass
5.1 --- a/lib/posix/io.py Thu Dec 08 19:29:12 2016 +0100
5.2 +++ b/lib/posix/io.py Thu Dec 08 21:45:09 2016 +0100
5.3 @@ -19,6 +19,8 @@
5.4 this program. If not, see <http://www.gnu.org/licenses/>.
5.5 """
5.6
5.7 +from __builtins__.file import filestream
5.8 +from __builtins__.types import check_int, check_string
5.9 import native
5.10
5.11 # Abstractions for system-level files and streams.
5.12 @@ -37,17 +39,17 @@
5.13
5.14 "Read 'n' bytes from the file, returning a string."
5.15
5.16 - _check_int(n)
5.17 + check_int(n)
5.18 return read(self.fd, n)
5.19
5.20 def write(self, s):
5.21
5.22 "Write string 's' to the file."
5.23
5.24 - _check_string(s)
5.25 + check_string(s)
5.26 write(self.fd, s)
5.27
5.28 -class sysstream:
5.29 +class sysstream(filestream):
5.30
5.31 "A system-level stream object."
5.32
5.33 @@ -55,44 +57,8 @@
5.34
5.35 "Initialise the stream with the given 'fd' and 'mode'."
5.36
5.37 + get_using(filestream.__init__, self)(bufsize)
5.38 self.__data__ = fdopen(fd, mode)
5.39 - self.bufsize = bufsize
5.40 -
5.41 - def read(self, n=0):
5.42 -
5.43 - "Read 'n' bytes from the stream."
5.44 -
5.45 - _check_int(n)
5.46 -
5.47 - # Read any indicated number of bytes.
5.48 -
5.49 - if n > 0:
5.50 - return native._fread(self.__data__, n)
5.51 -
5.52 - # Read all remaining bytes.
5.53 -
5.54 - else:
5.55 - l = []
5.56 -
5.57 - # Read until end-of-file.
5.58 -
5.59 - try:
5.60 - while True:
5.61 - l.append(native._fread(self.__data__, self.bufsize))
5.62 -
5.63 - # Handle end-of-file reads.
5.64 -
5.65 - except EOFError:
5.66 - pass
5.67 -
5.68 - return "".join(l)
5.69 -
5.70 - def write(self, s):
5.71 -
5.72 - "Write string 's' to the stream."
5.73 -
5.74 - _check_string(s)
5.75 - native._fwrite(self.__data__, s)
5.76
5.77 # Standard streams.
5.78
5.79 @@ -118,8 +84,8 @@
5.80 'mode'.
5.81 """
5.82
5.83 - _check_fd(fd)
5.84 - _check_string(mode)
5.85 + check_int(fd)
5.86 + check_string(mode)
5.87 return native._fdopen(fd, mode)
5.88
5.89 def fpathconf(fd, name): pass
5.90 @@ -145,8 +111,8 @@
5.91 Read using the low-level file descriptor 'fd' the given number of bytes 'n'.
5.92 """
5.93
5.94 - _check_fd(fd)
5.95 - _check_int(n)
5.96 + check_int(fd)
5.97 + check_int(n)
5.98 return native._read(fd, n)
5.99
5.100 def times(): pass
5.101 @@ -159,8 +125,8 @@
5.102
5.103 "Write using the low-level file descriptor 'fd' the given string 's'."
5.104
5.105 - _check_fd(fd)
5.106 - _check_string(s)
5.107 + check_int(fd)
5.108 + check_string(s)
5.109 native._write(fd, s)
5.110
5.111 # Constants.
5.112 @@ -185,27 +151,4 @@
5.113 O_TRUNC = 512
5.114 O_WRONLY = 1
5.115
5.116 -# Type validation functions.
5.117 -
5.118 -def _check_fd(fd):
5.119 -
5.120 - "Check the given low-level file descriptor 'fd'."
5.121 -
5.122 - if not native._isinstance(fd, int):
5.123 - raise ValueError(fd)
5.124 -
5.125 -def _check_int(i):
5.126 -
5.127 - "Check the given int 'i'."
5.128 -
5.129 - if not native._isinstance(i, int):
5.130 - raise ValueError(i)
5.131 -
5.132 -def _check_string(s):
5.133 -
5.134 - "Check the given string 's'."
5.135 -
5.136 - if not native._isinstance(s, string):
5.137 - raise ValueError(s)
5.138 -
5.139 # vim: tabstop=4 expandtab shiftwidth=4
6.1 --- a/templates/native.c Thu Dec 08 19:29:12 2016 +0100
6.2 +++ b/templates/native.c Thu Dec 08 21:45:09 2016 +0100
6.3 @@ -680,13 +680,42 @@
6.4
6.5 /* Input/output. */
6.6
6.7 +__attr __fn_native__fopen(__attr __args[])
6.8 +{
6.9 + __attr * const filename = &__args[1];
6.10 + __attr * const mode = &__args[2];
6.11 + /* filename.__data__ interpreted as string */
6.12 + char *fn = __load_via_object(filename->value, __pos___data__).strvalue;
6.13 + /* mode.__data__ interpreted as string */
6.14 + char *s = __load_via_object(mode->value, __pos___data__).strvalue;
6.15 + FILE *f;
6.16 + __attr attr;
6.17 +
6.18 + errno = 0;
6.19 + f = fopen(fn, s);
6.20 +
6.21 + /* Produce an exception if the operation failed. */
6.22 +
6.23 + if (f == NULL)
6.24 + __raise_io_error(__new_int(errno));
6.25 +
6.26 + /* Return the __data__ attribute. */
6.27 +
6.28 + else
6.29 + {
6.30 + attr.context = 0;
6.31 + attr.datavalue = (void *) f;
6.32 + return attr;
6.33 + }
6.34 +}
6.35 +
6.36 __attr __fn_native__fdopen(__attr __args[])
6.37 {
6.38 __attr * const fd = &__args[1];
6.39 __attr * const mode = &__args[2];
6.40 /* fd.__data__ interpreted as int */
6.41 int i = __load_via_object(fd->value, __pos___data__).intvalue;
6.42 - /* str.__data__ interpreted as string */
6.43 + /* mode.__data__ interpreted as string */
6.44 char *s = __load_via_object(mode->value, __pos___data__).strvalue;
6.45 FILE *f;
6.46 __attr attr;
7.1 --- a/templates/native.h Thu Dec 08 19:29:12 2016 +0100
7.2 +++ b/templates/native.h Thu Dec 08 21:45:09 2016 +0100
7.3 @@ -100,6 +100,7 @@
7.4
7.5 /* Input/output. */
7.6
7.7 +__attr __fn_native__fopen(__attr __args[]);
7.8 __attr __fn_native__fdopen(__attr __args[]);
7.9 __attr __fn_native__fread(__attr __args[]);
7.10 __attr __fn_native__fwrite(__attr __args[]);
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/tests/read_file.py Thu Dec 08 21:45:09 2016 +0100
8.3 @@ -0,0 +1,15 @@
8.4 +try:
8.5 + f = open("tests/read_file.py") # this file!
8.6 +except IOError, exc:
8.7 + print "I/O error occurred:", exc.value
8.8 + raise
8.9 +
8.10 +try:
8.11 + s = f.read(5)
8.12 + print s # try:
8.13 + s = f.read(49)
8.14 + print s # f = open("tests/read_file.py") # this file!
8.15 + s = f.read()
8.16 + print s
8.17 +finally:
8.18 + f.close()
9.1 --- a/tests/read_stream.py Thu Dec 08 19:29:12 2016 +0100
9.2 +++ b/tests/read_stream.py Thu Dec 08 21:45:09 2016 +0100
9.3 @@ -1,7 +1,9 @@
9.4 from sys import stdin
9.5
9.6 +print "Reading 10 bytes..."
9.7 s = stdin.read(10)
9.8 print s
9.9
9.10 +print "Reading to end of file..."
9.11 s = stdin.read()
9.12 print s