Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(3819)

Side by Side Diff: Objects/fileobject.c

Issue 1706039: Added clearerr() to clear EOF state
Patch Set: Created 2 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/test/test_file.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* File object implementation */ 1 /* File object implementation */
2 2
3 #define PY_SSIZE_T_CLEAN 3 #define PY_SSIZE_T_CLEAN
4 #include "Python.h" 4 #include "Python.h"
5 #include "structmember.h" 5 #include "structmember.h"
6 6
7 #ifdef HAVE_SYS_TYPES_H 7 #ifdef HAVE_SYS_TYPES_H
8 #include <sys/types.h> 8 #include <sys/types.h>
9 #endif /* HAVE_SYS_TYPES_H */ 9 #endif /* HAVE_SYS_TYPES_H */
10 10
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after
864 if (v == NULL) 864 if (v == NULL)
865 return NULL; 865 return NULL;
866 bytesread = 0; 866 bytesread = 0;
867 for (;;) { 867 for (;;) {
868 Py_BEGIN_ALLOW_THREADS 868 Py_BEGIN_ALLOW_THREADS
869 errno = 0; 869 errno = 0;
870 chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread, 870 chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread,
871 buffersize - bytesread, f->f_fp, (PyObject *)f); 871 buffersize - bytesread, f->f_fp, (PyObject *)f);
872 Py_END_ALLOW_THREADS 872 Py_END_ALLOW_THREADS
873 if (chunksize == 0) { 873 if (chunksize == 0) {
874 » » » if (!ferror(f->f_fp)) 874 » » » if (!PyErr_ExceptionMatches(PyExc_IOError))
875 break; 875 break;
876 clearerr(f->f_fp);
877 /* When in non-blocking mode, data shouldn't 876 /* When in non-blocking mode, data shouldn't
878 * be discarded if a blocking signal was 877 * be discarded if a blocking signal was
879 * received. That will also happen if 878 * received. That will also happen if
880 * chunksize != 0, but bytesread < buffersize. */ 879 * chunksize != 0, but bytesread < buffersize. */
881 » » » if (bytesread > 0 && BLOCKED_ERRNO(errno)) 880 » » » if (bytesread > 0 && BLOCKED_ERRNO(errno)) {
881 » » » » PyErr_Clear();
882 break; 882 break;
883 » » » PyErr_SetFromErrno(PyExc_IOError); 883 » » » }
884 Py_DECREF(v); 884 Py_DECREF(v);
885 return NULL; 885 return NULL;
886 } 886 }
887 bytesread += chunksize; 887 bytesread += chunksize;
888 if (bytesread < buffersize) { 888 if (bytesread < buffersize) {
889 clearerr(f->f_fp); 889 clearerr(f->f_fp);
890 break; 890 break;
891 } 891 }
892 if (bytesrequested < 0) { 892 if (bytesrequested < 0) {
893 buffersize = new_buffersize(f, buffersize); 893 buffersize = new_buffersize(f, buffersize);
(...skipping 26 matching lines...) Expand all
920 if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo)) 920 if (!PyArg_ParseTuple(args, "w#", &ptr, &ntodo))
921 return NULL; 921 return NULL;
922 ndone = 0; 922 ndone = 0;
923 while (ntodo > 0) { 923 while (ntodo > 0) {
924 Py_BEGIN_ALLOW_THREADS 924 Py_BEGIN_ALLOW_THREADS
925 errno = 0; 925 errno = 0;
926 nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp, 926 nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp,
927 (PyObject *)f); 927 (PyObject *)f);
928 Py_END_ALLOW_THREADS 928 Py_END_ALLOW_THREADS
929 if (nnow == 0) { 929 if (nnow == 0) {
930 » » » if (!ferror(f->f_fp)) 930 » » » if (!PyErr_ExceptionMatches(PyExc_IOError))
931 break; 931 break;
932 PyErr_SetFromErrno(PyExc_IOError);
933 clearerr(f->f_fp);
934 return NULL; 932 return NULL;
935 } 933 }
936 ndone += nnow; 934 ndone += nnow;
937 ntodo -= nnow; 935 ntodo -= nnow;
938 } 936 }
939 return PyInt_FromSsize_t(ndone); 937 return PyInt_FromSsize_t(ndone);
940 } 938 }
941 939
942 /************************************************************************** 940 /**************************************************************************
943 Routine to get next line using platform fgets(). 941 Routine to get next line using platform fgets().
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
1415 else { 1413 else {
1416 Py_BEGIN_ALLOW_THREADS 1414 Py_BEGIN_ALLOW_THREADS
1417 errno = 0; 1415 errno = 0;
1418 nread = Py_UniversalNewlineFread(buffer+nfilled, 1416 nread = Py_UniversalNewlineFread(buffer+nfilled,
1419 buffersize-nfilled, f->f_fp, (PyObject *)f); 1417 buffersize-nfilled, f->f_fp, (PyObject *)f);
1420 Py_END_ALLOW_THREADS 1418 Py_END_ALLOW_THREADS
1421 shortread = (nread < buffersize-nfilled); 1419 shortread = (nread < buffersize-nfilled);
1422 } 1420 }
1423 if (nread == 0) { 1421 if (nread == 0) {
1424 sizehint = 0; 1422 sizehint = 0;
1425 » » » if (!ferror(f->f_fp)) 1423 » » » if (!PyErr_ExceptionMatches(PyExc_IOError))
1426 break; 1424 break;
1427 PyErr_SetFromErrno(PyExc_IOError);
1428 clearerr(f->f_fp);
1429 error: 1425 error:
1430 Py_DECREF(list); 1426 Py_DECREF(list);
1431 list = NULL; 1427 list = NULL;
1432 goto cleanup; 1428 goto cleanup;
1433 } 1429 }
1434 totalread += nread; 1430 totalread += nread;
1435 p = (char *)memchr(buffer+nfilled, '\n', nread); 1431 p = (char *)memchr(buffer+nfilled, '\n', nread);
1436 if (p == NULL) { 1432 if (p == NULL) {
1437 /* Need a larger buffer to fit this line */ 1433 /* Need a larger buffer to fit this line */
1438 nfilled += nread; 1434 nfilled += nread;
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after
1866 if ((f->f_buf = (char *)PyMem_Malloc(bufsize)) == NULL) { 1862 if ((f->f_buf = (char *)PyMem_Malloc(bufsize)) == NULL) {
1867 PyErr_NoMemory(); 1863 PyErr_NoMemory();
1868 return -1; 1864 return -1;
1869 } 1865 }
1870 Py_BEGIN_ALLOW_THREADS 1866 Py_BEGIN_ALLOW_THREADS
1871 errno = 0; 1867 errno = 0;
1872 chunksize = Py_UniversalNewlineFread( 1868 chunksize = Py_UniversalNewlineFread(
1873 f->f_buf, bufsize, f->f_fp, (PyObject *)f); 1869 f->f_buf, bufsize, f->f_fp, (PyObject *)f);
1874 Py_END_ALLOW_THREADS 1870 Py_END_ALLOW_THREADS
1875 if (chunksize == 0) { 1871 if (chunksize == 0) {
1876 » » if (ferror(f->f_fp)) { 1872 » » if (PyErr_ExceptionMatches(PyExc_IOError)) {
1877 » » » PyErr_SetFromErrno(PyExc_IOError);
1878 » » » clearerr(f->f_fp);
1879 drop_readahead(f); 1873 drop_readahead(f);
1880 return -1; 1874 return -1;
1881 } 1875 }
1882 } 1876 }
1883 f->f_bufptr = f->f_buf; 1877 f->f_bufptr = f->f_buf;
1884 f->f_bufend = f->f_buf + chunksize; 1878 f->f_bufend = f->f_buf + chunksize;
1885 return 0; 1879 return 0;
1886 } 1880 }
1887 1881
1888 /* Used by file_iternext. The returned string will start with 'skip' 1882 /* Used by file_iternext. The returned string will start with 'skip'
(...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after
2419 ** the whole conversion is skipped. Finally, the routine keeps track of 2413 ** the whole conversion is skipped. Finally, the routine keeps track of
2420 ** the different types of newlines seen. 2414 ** the different types of newlines seen.
2421 */ 2415 */
2422 size_t 2416 size_t
2423 Py_UniversalNewlineFread(char *buf, size_t n, 2417 Py_UniversalNewlineFread(char *buf, size_t n,
2424 FILE *stream, PyObject *fobj) 2418 FILE *stream, PyObject *fobj)
2425 { 2419 {
2426 char *dst = buf; 2420 char *dst = buf;
2427 PyFileObject *f = (PyFileObject *)fobj; 2421 PyFileObject *f = (PyFileObject *)fobj;
2428 int newlinetypes, skipnextlf; 2422 int newlinetypes, skipnextlf;
2423 size_t nread;
2429 2424
2430 assert(buf != NULL); 2425 assert(buf != NULL);
2431 assert(stream != NULL); 2426 assert(stream != NULL);
2432 2427
2433 if (!fobj || !PyFile_Check(fobj)) { 2428 if (!fobj || !PyFile_Check(fobj)) {
2434 errno = ENXIO; /* What can you do... */ 2429 errno = ENXIO; /* What can you do... */
2435 return 0; 2430 return 0;
2436 } 2431 }
2437 » if (!f->f_univ_newline) 2432 » if (!f->f_univ_newline) {
2438 » » return fread(buf, 1, n, stream); 2433 » » nread = fread(buf, 1, n, stream);
2434 » » if (nread == 0) {
2435 » » » if (ferror(stream))
2436 » » » » PyErr_SetFromErrno(PyExc_IOError);
2437 » » » clearerr(stream);
2438 » » }
2439 » » return nread;
2440 » }
2439 newlinetypes = f->f_newlinetypes; 2441 newlinetypes = f->f_newlinetypes;
2440 skipnextlf = f->f_skipnextlf; 2442 skipnextlf = f->f_skipnextlf;
2441 /* Invariant: n is the number of bytes remaining to be filled 2443 /* Invariant: n is the number of bytes remaining to be filled
2442 * in the buffer. 2444 * in the buffer.
2443 */ 2445 */
2444 while (n) { 2446 while (n) {
2445 size_t nread;
2446 int shortread; 2447 int shortread;
2447 char *src = dst; 2448 char *src = dst;
2448 2449
2449 nread = fread(dst, 1, n, stream); 2450 nread = fread(dst, 1, n, stream);
2450 assert(nread <= n); 2451 assert(nread <= n);
2451 » » if (nread == 0) 2452 » » if (nread == 0) {
2453 » » » if (ferror(stream)) {
2454 » » » » clearerr(stream);
2455 » » » » PyErr_SetFromErrno(PyExc_IOError);
2456 » » » » return 0;
2457 » » » }
2458 » » » clearerr(stream);
2452 break; 2459 break;
2460 }
2453 2461
2454 n -= nread; /* assuming 1 byte out for each in; will adjust */ 2462 n -= nread; /* assuming 1 byte out for each in; will adjust */
2455 shortread = n != 0; /* true iff EOF or error */ 2463 shortread = n != 0; /* true iff EOF or error */
2456 while (nread--) { 2464 while (nread--) {
2457 char c = *src++; 2465 char c = *src++;
2458 if (c == '\r') { 2466 if (c == '\r') {
2459 /* Save as LF and set flag to skip next LF. */ 2467 /* Save as LF and set flag to skip next LF. */
2460 *dst++ = '\n'; 2468 *dst++ = '\n';
2461 skipnextlf = 1; 2469 skipnextlf = 1;
2462 } 2470 }
(...skipping 24 matching lines...) Expand all
2487 } 2495 }
2488 } 2496 }
2489 f->f_newlinetypes = newlinetypes; 2497 f->f_newlinetypes = newlinetypes;
2490 f->f_skipnextlf = skipnextlf; 2498 f->f_skipnextlf = skipnextlf;
2491 return dst - buf; 2499 return dst - buf;
2492 } 2500 }
2493 2501
2494 #ifdef __cplusplus 2502 #ifdef __cplusplus
2495 } 2503 }
2496 #endif 2504 #endif
OLDNEW
« no previous file with comments | « Lib/test/test_file.py ('k') | no next file » | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7