diff options
author | Guido van Rossum <guido@python.org> | 2001-01-05 14:43:05 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 2001-01-05 14:43:05 (GMT) |
commit | 1187aa4d33d672431d4cc6019ecaf635ca90bfc2 (patch) | |
tree | 19004b912f5cbaccce7d7ed9a62fb2dfbc6e2d57 /Objects/fileobject.c | |
parent | 742bb6f9fda7043cc1ec0f1937b2dd1d0ecb6ab6 (diff) | |
download | cpython-1187aa4d33d672431d4cc6019ecaf635ca90bfc2.zip cpython-1187aa4d33d672431d4cc6019ecaf635ca90bfc2.tar.gz cpython-1187aa4d33d672431d4cc6019ecaf635ca90bfc2.tar.bz2 |
Restructured get_line() for clarity and speed.
- The raw_input() functionality is moved to a separate function.
- Drop GNU getline() in favor of getc_unlocked(), which exists on more
platforms (and is even a tad faster on my system).
Diffstat (limited to 'Objects/fileobject.c')
-rw-r--r-- | Objects/fileobject.c | 125 |
1 files changed, 59 insertions, 66 deletions
diff --git a/Objects/fileobject.c b/Objects/fileobject.c index ea8fe9d..35d1034 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -639,49 +639,28 @@ file_readinto(PyFileObject *f, PyObject *args) Size argument interpretation: > 0: max length; = 0: read arbitrary line; - < 0: strip trailing '\n', raise EOFError if EOF reached immediately + < 0: illegal (use get_line_raw() instead) */ +#ifdef HAVE_GETC_UNLOCKED +#define GETC(f) getc_unlocked(f) +#define FLOCKFILE(f) flockfile(f) +#define FUNLOCKFILE(f) funlockfile(f) +#else +#define GETC(f) getc(f) +#define FLOCKFILE(f) +#define FUNLOCKFILE(f) +#endif + static PyObject * get_line(PyFileObject *f, int n) { - register FILE *fp = f->f_fp; - register int c; + FILE *fp = f->f_fp; + int c; char *buf, *end; size_t n1, n2; PyObject *v; -#if defined(HAVE_GETLINE) && defined(_GNU_SOURCE) - /* Use GNU libc extension getline() for arbitrary-sized lines */ - if (n == 0) { - size_t size = 0; - buf = NULL; - Py_BEGIN_ALLOW_THREADS - n1 = getline(&buf, &size, fp); - Py_END_ALLOW_THREADS - if (n1 == -1) { - if (buf){ - free(buf); - } - clearerr(fp); - if (PyErr_CheckSignals()) { - return NULL; - } - if (n < 0 && feof(fp)) { - PyErr_SetString(PyExc_EOFError, - "EOF when reading a line"); - return NULL; - } - return PyString_FromStringAndSize(NULL, 0); - } - /* No error */ - - v = PyString_FromStringAndSize(buf, n1); - free(buf); - return v; - } -#endif - n2 = n > 0 ? n : 100; v = PyString_FromStringAndSize((char *)NULL, n2); if (v == NULL) @@ -689,48 +668,40 @@ get_line(PyFileObject *f, int n) buf = BUF(v); end = buf + n2; - Py_BEGIN_ALLOW_THREADS for (;;) { - if ((c = getc(fp)) == EOF) { + Py_BEGIN_ALLOW_THREADS + FLOCKFILE(fp); + while ((c = GETC(fp)) != EOF && + (*buf++ = c) != '\n' && + buf != end) + ; + FUNLOCKFILE(fp); + Py_END_ALLOW_THREADS + if (c == '\n') + break; + if (c == EOF) { clearerr(fp); - Py_BLOCK_THREADS if (PyErr_CheckSignals()) { Py_DECREF(v); return NULL; } - if (n < 0 && buf == BUF(v)) { - Py_DECREF(v); - PyErr_SetString(PyExc_EOFError, - "EOF when reading a line"); - return NULL; - } - Py_UNBLOCK_THREADS break; } - if ((*buf++ = c) == '\n') { - if (n < 0) - buf--; + /* Must be because buf == end */ + if (n > 0) break; + n1 = n2; + n2 += 1000; + if (n2 > INT_MAX) { + PyErr_SetString(PyExc_OverflowError, + "line is longer than a Python string can hold"); + return NULL; } - if (buf == end) { - if (n > 0) - break; - n1 = n2; - n2 += 1000; - if (n2 > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, - "line is longer than a Python string can hold"); - return NULL; - } - Py_BLOCK_THREADS - if (_PyString_Resize(&v, n2) < 0) - return NULL; - Py_UNBLOCK_THREADS - buf = BUF(v) + n1; - end = BUF(v) + n2; - } + if (_PyString_Resize(&v, n2) < 0) + return NULL; + buf = BUF(v) + n1; + end = BUF(v) + n2; } - Py_END_ALLOW_THREADS n1 = buf - BUF(v); if (n1 != n2) @@ -738,6 +709,25 @@ get_line(PyFileObject *f, int n) return v; } +/* Internal routine to get a line for raw_input(): + strip trailing '\n', raise EOFError if EOF reached immediately +*/ + +static PyObject * +get_line_raw(PyFileObject *f) +{ + PyObject *line; + + line = get_line(f, 0); + if (line == NULL || PyString_GET_SIZE(line) > 0) + return line; + else { + Py_DECREF(line); + PyErr_SetString(PyExc_EOFError, "EOF when reading a line"); + return NULL; + } +} + /* External C interface */ PyObject * @@ -796,7 +786,10 @@ PyFile_GetLine(PyObject *f, int n) } if (((PyFileObject*)f)->f_fp == NULL) return err_closed(); - return get_line((PyFileObject *)f, n); + if (n < 0) + return get_line_raw((PyFileObject *)f); + else + return get_line((PyFileObject *)f, n); } /* Python method */ |