summaryrefslogtreecommitdiffstats
path: root/Objects/fileobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2001-01-05 14:43:05 (GMT)
committerGuido van Rossum <guido@python.org>2001-01-05 14:43:05 (GMT)
commit1187aa4d33d672431d4cc6019ecaf635ca90bfc2 (patch)
tree19004b912f5cbaccce7d7ed9a62fb2dfbc6e2d57 /Objects/fileobject.c
parent742bb6f9fda7043cc1ec0f1937b2dd1d0ecb6ab6 (diff)
downloadcpython-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.c125
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 */