Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1187aa4

Browse files
committed
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).
1 parent 742bb6f commit 1187aa4

1 file changed

Lines changed: 59 additions & 66 deletions

File tree

Objects/fileobject.c

Lines changed: 59 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -639,105 +639,95 @@ file_readinto(PyFileObject *f, PyObject *args)
639639
Size argument interpretation:
640640
> 0: max length;
641641
= 0: read arbitrary line;
642-
< 0: strip trailing '\n', raise EOFError if EOF reached immediately
642+
< 0: illegal (use get_line_raw() instead)
643643
*/
644644

645+
#ifdef HAVE_GETC_UNLOCKED
646+
#define GETC(f) getc_unlocked(f)
647+
#define FLOCKFILE(f) flockfile(f)
648+
#define FUNLOCKFILE(f) funlockfile(f)
649+
#else
650+
#define GETC(f) getc(f)
651+
#define FLOCKFILE(f)
652+
#define FUNLOCKFILE(f)
653+
#endif
654+
645655
static PyObject *
646656
get_line(PyFileObject *f, int n)
647657
{
648-
register FILE *fp = f->f_fp;
649-
register int c;
658+
FILE *fp = f->f_fp;
659+
int c;
650660
char *buf, *end;
651661
size_t n1, n2;
652662
PyObject *v;
653663

654-
#if defined(HAVE_GETLINE) && defined(_GNU_SOURCE)
655-
/* Use GNU libc extension getline() for arbitrary-sized lines */
656-
if (n == 0) {
657-
size_t size = 0;
658-
buf = NULL;
659-
Py_BEGIN_ALLOW_THREADS
660-
n1 = getline(&buf, &size, fp);
661-
Py_END_ALLOW_THREADS
662-
if (n1 == -1) {
663-
if (buf){
664-
free(buf);
665-
}
666-
clearerr(fp);
667-
if (PyErr_CheckSignals()) {
668-
return NULL;
669-
}
670-
if (n < 0 && feof(fp)) {
671-
PyErr_SetString(PyExc_EOFError,
672-
"EOF when reading a line");
673-
return NULL;
674-
}
675-
return PyString_FromStringAndSize(NULL, 0);
676-
}
677-
/* No error */
678-
679-
v = PyString_FromStringAndSize(buf, n1);
680-
free(buf);
681-
return v;
682-
}
683-
#endif
684-
685664
n2 = n > 0 ? n : 100;
686665
v = PyString_FromStringAndSize((char *)NULL, n2);
687666
if (v == NULL)
688667
return NULL;
689668
buf = BUF(v);
690669
end = buf + n2;
691670

692-
Py_BEGIN_ALLOW_THREADS
693671
for (;;) {
694-
if ((c = getc(fp)) == EOF) {
672+
Py_BEGIN_ALLOW_THREADS
673+
FLOCKFILE(fp);
674+
while ((c = GETC(fp)) != EOF &&
675+
(*buf++ = c) != '\n' &&
676+
buf != end)
677+
;
678+
FUNLOCKFILE(fp);
679+
Py_END_ALLOW_THREADS
680+
if (c == '\n')
681+
break;
682+
if (c == EOF) {
695683
clearerr(fp);
696-
Py_BLOCK_THREADS
697684
if (PyErr_CheckSignals()) {
698685
Py_DECREF(v);
699686
return NULL;
700687
}
701-
if (n < 0 && buf == BUF(v)) {
702-
Py_DECREF(v);
703-
PyErr_SetString(PyExc_EOFError,
704-
"EOF when reading a line");
705-
return NULL;
706-
}
707-
Py_UNBLOCK_THREADS
708688
break;
709689
}
710-
if ((*buf++ = c) == '\n') {
711-
if (n < 0)
712-
buf--;
690+
/* Must be because buf == end */
691+
if (n > 0)
713692
break;
693+
n1 = n2;
694+
n2 += 1000;
695+
if (n2 > INT_MAX) {
696+
PyErr_SetString(PyExc_OverflowError,
697+
"line is longer than a Python string can hold");
698+
return NULL;
714699
}
715-
if (buf == end) {
716-
if (n > 0)
717-
break;
718-
n1 = n2;
719-
n2 += 1000;
720-
if (n2 > INT_MAX) {
721-
PyErr_SetString(PyExc_OverflowError,
722-
"line is longer than a Python string can hold");
723-
return NULL;
724-
}
725-
Py_BLOCK_THREADS
726-
if (_PyString_Resize(&v, n2) < 0)
727-
return NULL;
728-
Py_UNBLOCK_THREADS
729-
buf = BUF(v) + n1;
730-
end = BUF(v) + n2;
731-
}
700+
if (_PyString_Resize(&v, n2) < 0)
701+
return NULL;
702+
buf = BUF(v) + n1;
703+
end = BUF(v) + n2;
732704
}
733-
Py_END_ALLOW_THREADS
734705

735706
n1 = buf - BUF(v);
736707
if (n1 != n2)
737708
_PyString_Resize(&v, n1);
738709
return v;
739710
}
740711

712+
/* Internal routine to get a line for raw_input():
713+
strip trailing '\n', raise EOFError if EOF reached immediately
714+
*/
715+
716+
static PyObject *
717+
get_line_raw(PyFileObject *f)
718+
{
719+
PyObject *line;
720+
721+
line = get_line(f, 0);
722+
if (line == NULL || PyString_GET_SIZE(line) > 0)
723+
return line;
724+
else {
725+
Py_DECREF(line);
726+
PyErr_SetString(PyExc_EOFError, "EOF when reading a line");
727+
return NULL;
728+
}
729+
}
730+
741731
/* External C interface */
742732

743733
PyObject *
@@ -796,7 +786,10 @@ PyFile_GetLine(PyObject *f, int n)
796786
}
797787
if (((PyFileObject*)f)->f_fp == NULL)
798788
return err_closed();
799-
return get_line((PyFileObject *)f, n);
789+
if (n < 0)
790+
return get_line_raw((PyFileObject *)f);
791+
else
792+
return get_line((PyFileObject *)f, n);
800793
}
801794

802795
/* Python method */

0 commit comments

Comments
 (0)