Commit ce5ba841 authored by Guido van Rossum's avatar Guido van Rossum

Fixed read() and readline() to do arbitrarily long reads.

And readline() now reads null bytes correctly.
Added tell(), seek() and flush().
parent 7ff04b39
......@@ -32,6 +32,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#include "allobjects.h"
#define BUF(v) GETSTRINGVALUE((stringobject *)v)
#include "errno.h"
#ifndef errno
extern int errno;
......@@ -161,35 +163,132 @@ file_close(f, args)
}
static object *
file_read(f, args)
file_seek(f, args)
fileobject *f;
object *args;
{
int n;
object *v;
long offset;
long whence;
if (f->f_fp == NULL) {
err_badarg();
return NULL;
}
if (args == NULL || !is_intobject(args)) {
if (args != NULL && is_intobject(args)) {
offset = getintvalue(args);
whence = 0; /* SEEK_SET */
}
else {
if (!getlonglongargs(args, &offset, &whence))
return NULL;
}
errno = 0;
if (fseek(f->f_fp, offset, (int)whence) != 0) {
if (errno == 0)
errno = EIO;
return err_errno(RuntimeError);
}
INCREF(None);
return None;
}
static object *
file_tell(f, args)
fileobject *f;
object *args;
{
long offset;
if (args != NULL || f->f_fp == NULL) {
err_badarg();
return NULL;
}
errno = 0;
offset = ftell(f->f_fp);
if (offset == -1L) {
if (errno == 0)
errno = EIO;
return err_errno(RuntimeError);
}
return newintobject(offset);
}
static object *
file_flush(f, args)
fileobject *f;
object *args;
{
if (args != NULL || f->f_fp == NULL) {
err_badarg();
return NULL;
}
errno = 0;
if (fflush(f->f_fp) != 0) {
if (errno == 0)
errno = EIO;
return err_errno(RuntimeError);
}
INCREF(None);
return None;
}
static object *
file_read(f, args)
fileobject *f;
object *args;
{
int n, n1, n2, n3;
object *v;
if (f->f_fp == NULL) {
err_badarg();
return NULL;
}
n = getintvalue(args);
if (args == 0)
n = 0;
else {
if (!getintarg(args, &n))
return NULL;
if (n < 0) {
err_badarg();
return NULL;
}
v = newsizedstringobject((char *)NULL, n);
}
n2 = n != 0 ? n : BUFSIZ;
v = newsizedstringobject((char *)NULL, n2);
if (v == NULL)
return NULL;
n = fread(getstringvalue(v), 1, n, f->f_fp);
/* EOF is reported as an empty string */
/* XXX should detect real I/O errors? */
resizestring(&v, n);
n1 = 0;
for (;;) {
n3 = fread(BUF(v)+n1, 1, n2-n1, f->f_fp);
/* XXX Error check? */
if (n3 == 0)
break;
n1 += n3;
if (n1 == n)
break;
if (n == 0) {
n2 = n1 + BUFSIZ;
if (resizestring(&v, n2) < 0)
return NULL;
}
}
if (n1 != n2)
resizestring(&v, n1);
return v;
}
/* Read a line.
Without argument, or with a zero argument, read until end of line
or EOF, whichever comes first.
With a positive argument n, read at most n bytes until end of line
or EOF, whichever comes first.
Negative and non-integer arguments are illegal.
When EOF is hit immediately, return an empty string.
A newline character is returned as the last character of the buffer
if it is read.
*/
/* XXX Should this be unified with raw_input()? */
static object *
......@@ -197,45 +296,83 @@ file_readline(f, args)
fileobject *f;
object *args;
{
int n;
register FILE *fp;
register int c;
register char *buf, *end;
int n, n1, n2;
object *v;
if (f->f_fp == NULL) {
if ((fp = f->f_fp) == NULL) {
err_badarg();
return NULL;
}
if (args == NULL) {
n = 10000; /* XXX should really be unlimited */
}
else if (is_intobject(args)) {
n = getintvalue(args);
if (args == NULL)
n = 0; /* Unlimited */
else {
if (!getintarg(args, &n))
return NULL;
if (n < 0) {
err_badarg();
return NULL;
}
}
else {
err_badarg();
return NULL;
}
v = newsizedstringobject((char *)NULL, n);
n2 = n != 0 ? n : 100;
v = newsizedstringobject((char *)NULL, n2);
if (v == NULL)
return NULL;
#ifndef THINK_C_3_0
/* XXX Think C 3.0 wrongly reads up to n characters... */
n = n+1;
#endif
if (fgets(getstringvalue(v), n, f->f_fp) == NULL) {
/* EOF is reported as an empty string */
/* XXX should detect real I/O errors? */
n = 0;
buf = BUF(v);
end = buf + n2;
for (;;) {
if ((c = getc(fp)) == EOF || (*buf++ = c) == '\n')
break;
/* XXX Error check? */
if (buf == end) {
if (n != 0)
break;
n1 = n2;
n2 += 1000;
if (resizestring(&v, n2) < 0)
return NULL;
buf = BUF(v) + n1;
end = BUF(v) + n2;
}
else {
n = strlen(getstringvalue(v));
}
resizestring(&v, n);
n1 = buf - BUF(v);
if (n1 != n2)
resizestring(&v, n1);
return v;
}
static object *
file_readlines(f, args)
fileobject *f;
object *args;
{
object *list;
object *line;
if ((list = newlistobject(0)) == NULL)
return NULL;
for (;;) {
line = file_readline(f, args);
if (line != NULL && getstringsize(line) == 0) {
DECREF(line);
break;
}
if (line == NULL || addlistitem(list, line) != 0) {
DECREF(list);
XDECREF(line);
return NULL;
}
DECREF(line);
}
return list;
}
static object *
file_write(f, args)
fileobject *f;
......@@ -263,10 +400,14 @@ file_write(f, args)
}
static struct methodlist file_methods[] = {
{"write", file_write},
{"close", file_close},
{"flush", file_flush},
{"read", file_read},
{"readline", file_readline},
{"close", file_close},
{"readlines", file_readlines},
{"seek", file_seek},
{"tell", file_tell},
{"write", file_write},
{NULL, NULL} /* sentinel */
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment