char* p; /* temp */ char buf[MAXBUFSIZE]; PyObject* v; /* the string object result */ char* pvfree; /* address of next free slot */ char* pvend; /* address one beyond last free slot */ size_t nfree; /* # of free buffer slots; pvend-pvfree */ size_t total_v_size; /* total # of slots in buffer */ size_t increment; /* amount to increment the buffer */ size_t prev_v_size; /* Optimize for normal case: avoid _PyString_Resize if at all * possible via first reading into stack buffer "buf". */ total_v_size = INITBUFSIZE; /* start small and pray */ pvfree = buf; for (;;) { Py_BEGIN_ALLOW_THREADS pvend = buf + total_v_size; nfree = pvend - pvfree; memset(pvfree, '\n', nfree); assert(nfree < INT_MAX); /* Should be atmost MAXBUFSIZE */ p = fgets(pvfree, (int)nfree, fp); Py_END_ALLOW_THREADS if (p == NULL) { clearerr(fp); if (PyErr_CheckSignals()) return NULL; v = PyString_FromStringAndSize(buf, pvfree - buf); return v; } /* fgets read *something* */ p = memchr(pvfree, '\n', nfree); if (p != NULL) { /* Did the \n come from fgets or from us? * Since fgets stops at the first \n, and then writes * \0, if it's from fgets a \0 must be next. But if * that's so, it could not have come from us, since * the \n's we filled the buffer with have only more * \n's to the right. */ if (p+1 < pvend && *(p+1) == '\0') { /* It's from fgets: we win! In particular, * we haven't done any mallocs yet, and can * build the final result on the first try. */ ++p; /* include \n from fgets */ } else { /* Must be from us: fgets didn't fill the * buffer and didn't find a newline, so it * must be the last and newline-free line of * the file. */ assert(p > pvfree && *(p-1) == '\0'); --p; /* don't include \0 from fgets */ } v = PyString_FromStringAndSize(buf, p - buf); return v; } /* yuck: fgets overwrote all the newlines, i.e. the entire * buffer. So this line isn't over yet, or maybe it is but * we're exactly at EOF. If we haven't already, try using the * rest of the stack buffer. */ assert(*(pvend-1) == '\0'); if (pvfree == buf) { pvfree = pvend - 1; /* overwrite trailing null */ total_v_size = MAXBUFSIZE; } else break; } /* The stack buffer isn't big enough; malloc a string object and read * into its buffer. */ total_v_size = MAXBUFSIZE << 1; v = PyString_FromStringAndSize((char*)NULL, (int)total_v_size); if (v == NULL) return v; /* copy over everything except the last null byte */ memcpy(BUF(v), buf, MAXBUFSIZE-1); pvfree = BUF(v) + MAXBUFSIZE - 1; /* Keep reading stuff into v; if it ever ends successfully, break * after setting p one beyond the end of the line. The code here is * very much like the code above, except reads into v's buffer; see * the code above for detailed comments about the logic. */ for (;;) { Py_BEGIN_ALLOW_THREADS pvend = BUF(v) + total_v_size; nfree = pvend - pvfree; memset(pvfree, '\n', nfree); assert(nfree < INT_MAX); p = fgets(pvfree, (int)nfree, fp); Py_END_ALLOW_THREADS if (p == NULL) { clearerr(fp); if (PyErr_CheckSignals()) { Py_DECREF(v); return NULL; } p = pvfree; break; } p = memchr(pvfree, '\n', nfree); if (p != NULL) { if (p+1 < pvend && *(p+1) == '\0') { /* \n came from fgets */ ++p; break; } /* \n came from us; last line of file, no newline */ assert(p > pvfree && *(p-1) == '\0'); --p; break; } /* expand buffer and try again */ assert(*(pvend-1) == '\0'); increment = total_v_size >> 2; /* mild exponential growth */ prev_v_size = total_v_size; total_v_size += increment; /* check for overflow */ if (total_v_size <= prev_v_size || total_v_size > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "line is longer than a Python string can hold"); Py_DECREF(v); return NULL; } if (_PyString_Resize(&v, (int)total_v_size) < 0) return NULL; /* overwrite the trailing null byte */ pvfree = BUF(v) + (prev_v_size - 1); } if (BUF(v) + total_v_size != p) _PyString_Resize(&v, p - BUF(v)); return v;#undef INITBUFSIZE#undef MAXBUFSIZE}#endif /* ifdef USE_FGETS_IN_GETLINE */ /* Internal routine to get a line. Size argument interpretation: > 0: max length; <= 0: read arbitrary line*/ static PyObject *get_line(PyFileObject *f, int n){ FILE *fp = f->f_fp; int c; char *buf, *end; size_t total_v_size; /* total # of slots in buffer */ size_t used_v_size; /* # used slots in buffer */ size_t increment; /* amount to increment the buffer */ PyObject *v; int newlinetypes = f->f_newlinetypes; int skipnextlf = f->f_skipnextlf; int univ_newline = f->f_univ_newline; #if defined(USE_FGETS_IN_GETLINE) if (n <= 0 && !univ_newline ) return getline_via_fgets(fp);#endif total_v_size = n > 0 ? n : 100; v = PyString_FromStringAndSize((char *)NULL, total_v_size); if (v == NULL) return NULL; buf = BUF(v); end = buf + total_v_size; for (;;) { Py_BEGIN_ALLOW_THREADS FLOCKFILE(fp); if (univ_newline) { c = 'x'; /* Shut up gcc warning */ while ( buf != end && (c = GETC(fp)) != EOF ) { if (skipnextlf ) { skipnextlf = 0; if (c == '\n') { /* Seeing a \n here with * skipnextlf true means we * saw a \r before. */ newlinetypes |= NEWLINE_CRLF; c = GETC(fp); if (c == EOF) break; } else { newlinetypes |= NEWLINE_CR; } } if (c == '\r') { skipnextlf = 1; c = '\n'; } else if ( c == '\n') newlinetypes |= NEWLINE_LF; *buf++ = c; if (c == '\n') break; } if ( c == EOF && skipnextlf ) newlinetypes |= NEWLINE_CR; } else /* If not universal newlines use the normal loop */ while ((c = GETC(fp)) != EOF && (*buf++ = c) != '\n' && buf != end) ; FUNLOCKFILE(fp); Py_END_ALLOW_THREADS f->f_newlinetypes = newlinetypes; f->f_skipnextlf = skipnextlf; if (c == '\n') break; if (c == EOF) { if (ferror(fp)) { PyErr_SetFromErrno(PyExc_IOError); clearerr(fp); Py_DECREF(v); return NULL; } clearerr(fp); if (PyErr_CheckSignals()) { Py_DECREF(v); return NULL; } break; } /* Must be because buf == end */ if (n > 0) break; used_v_size = total_v_size; increment = total_v_size >> 2; /* mild exponential growth */ total_v_size += increment; if (total_v_size > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "line is longer than a Python string can hold"); Py_DECREF(v); return NULL; } if (_PyString_Resize(&v, total_v_size) < 0) return NULL; buf = BUF(v) + used_v_size; end = BUF(v) + total_v_size; } used_v_size = buf - BUF(v); if (used_v_size != total_v_size) _PyString_Resize(&v, used_v_size); return v;} /* External C interface */ PyObject *PyFile_GetLine(PyObject *f, int n){ PyObject *result; if (f == NULL) { PyErr_BadInternalCall(); return NULL; } if (PyFile_Check(f)) { PyFileObject *fo = (PyFileObject *)f; if (fo->f_fp == NULL) return err_closed(); /* refuse to mix with f.next() */ if (fo->f_buf != NULL && (fo->f_bufend - fo->f_bufptr) > 0 && fo->f_buf[0] != '\0') return err_iterbuffered(); result = get_line(fo, n); } else { PyObject *reader; PyObject *args; reader = PyObject_GetAttrString(f, "readline"); if (reader == NULL) return NULL; if (n <= 0) args = PyTuple_New(0); else args = Py_BuildValue("(i)", n); if (args == NULL) { Py_DECREF(reader); return NULL; } result = PyEval_CallObject(reader, args); Py_DECREF(reader); Py_DECREF(args); if (result != NULL && !PyString_Check(result) && !PyUnicode_Check(result)) { Py_DECREF(result); result = NULL; PyErr_SetString(PyExc_TypeError, "object.readline() returned non-string"); } } if (n < 0 && result != NULL && PyString_Check(result)) { char *s = PyString_AS_STRING(result); Py_ssize_t len = PyString_GET_SIZE(result); if (len == 0) { Py_DECREF(result); result = NULL; PyErr_SetString(PyExc_EOFError, "EOF when reading a line"); } else if (s[len-1] == '\n') { if (result->ob_refcnt == 1) _PyString_Resize(&result, len-1); else { PyObject *v; v = PyString_FromStringAndSize(s, len-1); Py_DECREF(result); result = v; } } }#ifdef Py_USING_UNICODE if (n < 0 && result != NULL && PyUnicode_Check(result)) { Py_UNICODE *s = PyUnicode_AS_UNICODE(result); Py_ssize_t len = PyUnicode_GET_SIZE(result); if (len == 0) { Py_DECREF(result); result = NULL; PyErr_SetString(PyExc_EOFError, "EOF when reading a line"); } else if (s[len-1] == '\n') { if (result->ob_refcnt == 1) PyUnicode_Resize(&result, len-1); else { PyObject *v; v = PyUnicode_FromUnicode(s, len-1); Py_DECREF(result); result = v; } } }#endif return result;} /* Python method */ static PyObject *file_readline(PyFileObject *f, PyObject *args){ int n = -1; if (f->f_fp == NULL) return err_closed(); /* refuse to mix with f.next() */ if (f->f_buf != NULL && (f->f_bufend - f->f_bufptr) > 0 && f->f_buf[0] != '\0') return err_iterbuffered(); if (!PyArg_ParseTuple(args, "|i:readline", &n)) return NULL; if (n == 0) return PyString_FromString(""); if (n < 0) n = 0; return get_line(f, n);} static PyObject *file_readlines(PyFileObject *f, PyObject *args){ long sizehint = 0; PyObject *list; PyObject *line; char small_buffer[SMALLCHUNK]; char *buffer = small_buffer; size_t buffersize = SMALLCHUNK; PyObject *big_buffer = NULL; size_t nfilled = 0; size_t nread; size_t totalread = 0; char *p, *q, *end; int err; int shortread = 0; if (f->f_fp == NULL) return err_closed(); /* refuse to mix with f.next() */ if (f->f_buf != NULL && (f->f_bufend - f->f_bufptr) > 0 && f->f_buf[0] != '\0') return err_iterbuffered(); if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint)) return NULL; if ((list = PyList_New(0)) == NULL) return NULL; for (;;) { if (shortread) nread = 0; else { Py_BEGIN_ALLOW_THREADS errno = 0; nread = Py_UniversalNewlineFread(buffer+nfilled, buffersize-nfilled, f->f_fp, (PyObject *)f); Py_END_ALLOW_THREADS shortread = (nread < buffersize-nfilled); } if (nread == 0) { sizehint = 0; if (!ferror(f->f_fp)) break; PyErr_SetFromErrno(PyExc_IOError); clearerr(f->f_fp); error: Py_DECREF(list); list = NULL; goto cleanup; } totalread += nread; p = (char *)memchr(buffer+nfilled, '\n', nread); if (p == NULL) { /* Need a larger buffer to fit this line */ nfilled += nread; buffersize *= 2; if (buffersize > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "line is longer than a Python string can hold"); goto error; } if (big_buffer == NULL) { /* Create the big buffer */ big_buffer = PyString_FromStringAndSize( NULL, buffersize); if (big_buffer == NULL) goto error; buffer = PyString_AS_STRING(big_buffer); memcpy(buffer, small_buffer, nfilled); } else { /* Grow the big buffer */ if ( _PyString_Resize(&big_buffer, buffersize) < 0 ) goto error; buffer = PyString_AS_STRING(big_buffer); } continue; } end = buffer+nfilled+nread; q = buffer; do { /* Process complete lines */ p++; line = PyString_FromStringAndSize(q, p-q); if (line == NULL) goto error; err = PyList_Append(list, line); Py_DECREF(line); if (err != 0) goto error; q = p; p = (char *)memchr(q, '\n', end-q); } while (p != NULL); /* Move the remaining incomplete line to the start */ nfilled = end-q; memmove(buffer, q, nfilled); if (sizehint > 0) if (totalread >= (size_t)sizehint) break; } if (nfilled != 0) { /* Partial last line */ line = PyString_FromStringAndSize(buffer, nfilled); if (line == NULL) goto error; if (sizehint > 0) { /* Need to complete the last line */ PyObject *rest = get_line(f, 0); if (rest == NULL) { Py_DECREF(line); goto error; } PyString_Concat(&line, rest); Py_DECREF(rest); if (line == NULL) goto error; } err = PyList_Append(list, line); Py_DECREF(line); if (err != 0) goto error; } cleanup: Py_XDECREF(big_buffer); return list;}Lines 1001–1500 of 2487. Previous lines Load more
char* p; /* temp */ char buf[MAXBUFSIZE]; PyObject* v; /* the string object result */ char* pvfree; /* address of next free slot */ char* pvend; /* address one beyond last free slot */ size_t nfree; /* # of free buffer slots; pvend-pvfree */ size_t total_v_size; /* total # of slots in buffer */ size_t increment; /* amount to increment the buffer */ size_t prev_v_size; /* Optimize for normal case: avoid _PyString_Resize if at all * possible via first reading into stack buffer "buf". */ total_v_size = INITBUFSIZE; /* start small and pray */ pvfree = buf; for (;;) { Py_BEGIN_ALLOW_THREADS pvend = buf + total_v_size; nfree = pvend - pvfree; memset(pvfree, '\n', nfree); assert(nfree < INT_MAX); /* Should be atmost MAXBUFSIZE */ p = fgets(pvfree, (int)nfree, fp); Py_END_ALLOW_THREADS if (p == NULL) { clearerr(fp); if (PyErr_CheckSignals()) return NULL; v = PyString_FromStringAndSize(buf, pvfree - buf); return v; } /* fgets read *something* */ p = memchr(pvfree, '\n', nfree); if (p != NULL) { /* Did the \n come from fgets or from us? * Since fgets stops at the first \n, and then writes * \0, if it's from fgets a \0 must be next. But if * that's so, it could not have come from us, since * the \n's we filled the buffer with have only more * \n's to the right. */ if (p+1 < pvend && *(p+1) == '\0') { /* It's from fgets: we win! In particular, * we haven't done any mallocs yet, and can * build the final result on the first try. */ ++p; /* include \n from fgets */ } else { /* Must be from us: fgets didn't fill the * buffer and didn't find a newline, so it * must be the last and newline-free line of * the file. */ assert(p > pvfree && *(p-1) == '\0'); --p; /* don't include \0 from fgets */ } v = PyString_FromStringAndSize(buf, p - buf); return v; } /* yuck: fgets overwrote all the newlines, i.e. the entire * buffer. So this line isn't over yet, or maybe it is but * we're exactly at EOF. If we haven't already, try using the * rest of the stack buffer. */ assert(*(pvend-1) == '\0'); if (pvfree == buf) { pvfree = pvend - 1; /* overwrite trailing null */ total_v_size = MAXBUFSIZE; } else break; } /* The stack buffer isn't big enough; malloc a string object and read * into its buffer. */ total_v_size = MAXBUFSIZE << 1; v = PyString_FromStringAndSize((char*)NULL, (int)total_v_size); if (v == NULL) return v; /* copy over everything except the last null byte */ memcpy(BUF(v), buf, MAXBUFSIZE-1); pvfree = BUF(v) + MAXBUFSIZE - 1; /* Keep reading stuff into v; if it ever ends successfully, break * after setting p one beyond the end of the line. The code here is * very much like the code above, except reads into v's buffer; see * the code above for detailed comments about the logic. */ for (;;) { Py_BEGIN_ALLOW_THREADS pvend = BUF(v) + total_v_size; nfree = pvend - pvfree; memset(pvfree, '\n', nfree); assert(nfree < INT_MAX); p = fgets(pvfree, (int)nfree, fp); Py_END_ALLOW_THREADS if (p == NULL) { clearerr(fp); if (PyErr_CheckSignals()) { Py_DECREF(v); return NULL; } p = pvfree; break; } p = memchr(pvfree, '\n', nfree); if (p != NULL) { if (p+1 < pvend && *(p+1) == '\0') { /* \n came from fgets */ ++p; break; } /* \n came from us; last line of file, no newline */ assert(p > pvfree && *(p-1) == '\0'); --p; break; } /* expand buffer and try again */ assert(*(pvend-1) == '\0'); increment = total_v_size >> 2; /* mild exponential growth */ prev_v_size = total_v_size; total_v_size += increment; /* check for overflow */ if (total_v_size <= prev_v_size || total_v_size > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "line is longer than a Python string can hold"); Py_DECREF(v); return NULL; } if (_PyString_Resize(&v, (int)total_v_size) < 0) return NULL; /* overwrite the trailing null byte */ pvfree = BUF(v) + (prev_v_size - 1); } if (BUF(v) + total_v_size != p) _PyString_Resize(&v, p - BUF(v)); return v; #undef INITBUFSIZE #undef MAXBUFSIZE } #endif /* ifdef USE_FGETS_IN_GETLINE */ /* Internal routine to get a line. Size argument interpretation: > 0: max length; <= 0: read arbitrary line */ static PyObject * get_line(PyFileObject *f, int n) { FILE *fp = f->f_fp; int c; char *buf, *end; size_t total_v_size; /* total # of slots in buffer */ size_t used_v_size; /* # used slots in buffer */ size_t increment; /* amount to increment the buffer */ PyObject *v; int newlinetypes = f->f_newlinetypes; int skipnextlf = f->f_skipnextlf; int univ_newline = f->f_univ_newline; #if defined(USE_FGETS_IN_GETLINE) if (n <= 0 && !univ_newline ) return getline_via_fgets(fp); #endif total_v_size = n > 0 ? n : 100; v = PyString_FromStringAndSize((char *)NULL, total_v_size); if (v == NULL) return NULL; buf = BUF(v); end = buf + total_v_size; for (;;) { Py_BEGIN_ALLOW_THREADS FLOCKFILE(fp); if (univ_newline) { c = 'x'; /* Shut up gcc warning */ while ( buf != end && (c = GETC(fp)) != EOF ) { if (skipnextlf ) { skipnextlf = 0; if (c == '\n') { /* Seeing a \n here with * skipnextlf true means we * saw a \r before. */ newlinetypes |= NEWLINE_CRLF; c = GETC(fp); if (c == EOF) break; } else { newlinetypes |= NEWLINE_CR; } } if (c == '\r') { skipnextlf = 1; c = '\n'; } else if ( c == '\n') newlinetypes |= NEWLINE_LF; *buf++ = c; if (c == '\n') break; } if ( c == EOF && skipnextlf ) newlinetypes |= NEWLINE_CR; } else /* If not universal newlines use the normal loop */ while ((c = GETC(fp)) != EOF && (*buf++ = c) != '\n' && buf != end) ; FUNLOCKFILE(fp); Py_END_ALLOW_THREADS f->f_newlinetypes = newlinetypes; f->f_skipnextlf = skipnextlf; if (c == '\n') break; if (c == EOF) { if (ferror(fp)) { PyErr_SetFromErrno(PyExc_IOError); clearerr(fp); Py_DECREF(v); return NULL; } clearerr(fp); if (PyErr_CheckSignals()) { Py_DECREF(v); return NULL; } break; } /* Must be because buf == end */ if (n > 0) break; used_v_size = total_v_size; increment = total_v_size >> 2; /* mild exponential growth */ total_v_size += increment; if (total_v_size > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "line is longer than a Python string can hold"); Py_DECREF(v); return NULL; } if (_PyString_Resize(&v, total_v_size) < 0) return NULL; buf = BUF(v) + used_v_size; end = BUF(v) + total_v_size; } used_v_size = buf - BUF(v); if (used_v_size != total_v_size) _PyString_Resize(&v, used_v_size); return v; } /* External C interface */ PyObject * PyFile_GetLine(PyObject *f, int n) { PyObject *result; if (f == NULL) { PyErr_BadInternalCall(); return NULL; } if (PyFile_Check(f)) { PyFileObject *fo = (PyFileObject *)f; if (fo->f_fp == NULL) return err_closed(); /* refuse to mix with f.next() */ if (fo->f_buf != NULL && (fo->f_bufend - fo->f_bufptr) > 0 && fo->f_buf[0] != '\0') return err_iterbuffered(); result = get_line(fo, n); } else { PyObject *reader; PyObject *args; reader = PyObject_GetAttrString(f, "readline"); if (reader == NULL) return NULL; if (n <= 0) args = PyTuple_New(0); else args = Py_BuildValue("(i)", n); if (args == NULL) { Py_DECREF(reader); return NULL; } result = PyEval_CallObject(reader, args); Py_DECREF(reader); Py_DECREF(args); if (result != NULL && !PyString_Check(result) && !PyUnicode_Check(result)) { Py_DECREF(result); result = NULL; PyErr_SetString(PyExc_TypeError, "object.readline() returned non-string"); } } if (n < 0 && result != NULL && PyString_Check(result)) { char *s = PyString_AS_STRING(result); Py_ssize_t len = PyString_GET_SIZE(result); if (len == 0) { Py_DECREF(result); result = NULL; PyErr_SetString(PyExc_EOFError, "EOF when reading a line"); } else if (s[len-1] == '\n') { if (result->ob_refcnt == 1) _PyString_Resize(&result, len-1); else { PyObject *v; v = PyString_FromStringAndSize(s, len-1); Py_DECREF(result); result = v; } } } #ifdef Py_USING_UNICODE if (n < 0 && result != NULL && PyUnicode_Check(result)) { Py_UNICODE *s = PyUnicode_AS_UNICODE(result); Py_ssize_t len = PyUnicode_GET_SIZE(result); if (len == 0) { Py_DECREF(result); result = NULL; PyErr_SetString(PyExc_EOFError, "EOF when reading a line"); } else if (s[len-1] == '\n') { if (result->ob_refcnt == 1) PyUnicode_Resize(&result, len-1); else { PyObject *v; v = PyUnicode_FromUnicode(s, len-1); Py_DECREF(result); result = v; } } } #endif return result; } /* Python method */ static PyObject * file_readline(PyFileObject *f, PyObject *args) { int n = -1; if (f->f_fp == NULL) return err_closed(); /* refuse to mix with f.next() */ if (f->f_buf != NULL && (f->f_bufend - f->f_bufptr) > 0 && f->f_buf[0] != '\0') return err_iterbuffered(); if (!PyArg_ParseTuple(args, "|i:readline", &n)) return NULL; if (n == 0) return PyString_FromString(""); if (n < 0) n = 0; return get_line(f, n); } static PyObject * file_readlines(PyFileObject *f, PyObject *args) { long sizehint = 0; PyObject *list; PyObject *line; char small_buffer[SMALLCHUNK]; char *buffer = small_buffer; size_t buffersize = SMALLCHUNK; PyObject *big_buffer = NULL; size_t nfilled = 0; size_t nread; size_t totalread = 0; char *p, *q, *end; int err; int shortread = 0; if (f->f_fp == NULL) return err_closed(); /* refuse to mix with f.next() */ if (f->f_buf != NULL && (f->f_bufend - f->f_bufptr) > 0 && f->f_buf[0] != '\0') return err_iterbuffered(); if (!PyArg_ParseTuple(args, "|l:readlines", &sizehint)) return NULL; if ((list = PyList_New(0)) == NULL) return NULL; for (;;) { if (shortread) nread = 0; else { Py_BEGIN_ALLOW_THREADS errno = 0; nread = Py_UniversalNewlineFread(buffer+nfilled, buffersize-nfilled, f->f_fp, (PyObject *)f); Py_END_ALLOW_THREADS shortread = (nread < buffersize-nfilled); } if (nread == 0) { sizehint = 0; if (!ferror(f->f_fp)) break; PyErr_SetFromErrno(PyExc_IOError); clearerr(f->f_fp); error: Py_DECREF(list); list = NULL; goto cleanup; } totalread += nread; p = (char *)memchr(buffer+nfilled, '\n', nread); if (p == NULL) { /* Need a larger buffer to fit this line */ nfilled += nread; buffersize *= 2; if (buffersize > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "line is longer than a Python string can hold"); goto error; } if (big_buffer == NULL) { /* Create the big buffer */ big_buffer = PyString_FromStringAndSize( NULL, buffersize); if (big_buffer == NULL) goto error; buffer = PyString_AS_STRING(big_buffer); memcpy(buffer, small_buffer, nfilled); } else { /* Grow the big buffer */ if ( _PyString_Resize(&big_buffer, buffersize) < 0 ) goto error; buffer = PyString_AS_STRING(big_buffer); } continue; } end = buffer+nfilled+nread; q = buffer; do { /* Process complete lines */ p++; line = PyString_FromStringAndSize(q, p-q); if (line == NULL) goto error; err = PyList_Append(list, line); Py_DECREF(line); if (err != 0) goto error; q = p; p = (char *)memchr(q, '\n', end-q); } while (p != NULL); /* Move the remaining incomplete line to the start */ nfilled = end-q; memmove(buffer, q, nfilled); if (sizehint > 0) if (totalread >= (size_t)sizehint) break; } if (nfilled != 0) { /* Partial last line */ line = PyString_FromStringAndSize(buffer, nfilled); if (line == NULL) goto error; if (sizehint > 0) { /* Need to complete the last line */ PyObject *rest = get_line(f, 0); if (rest == NULL) { Py_DECREF(line); goto error; } PyString_Concat(&line, rest); Py_DECREF(rest); if (line == NULL) goto error; } err = PyList_Append(list, line); Py_DECREF(line); if (err != 0) goto error; } cleanup: Py_XDECREF(big_buffer); return list; }