8000 closes bpo-45479: Degunkify Py_UniversalNewlineFgets. by benjaminp · Pull Request #28965 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

closes bpo-45479: Degunkify Py_UniversalNewlineFgets. #28965

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 15, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 5 additions & 32 deletions Objects/fileobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,13 +239,7 @@ _PyLong_FileDescriptor_Converter(PyObject *o, void *ptr)
** Py_UniversalNewlineFgets is an fgets variation that understands
** all of \r, \n and \r\n conventions.
** The stream should be opened in binary mode.
** If fobj is NULL the routine always does newline conversion, and
** it may peek one char ahead to gobble the second char in \r\n.
** If fobj is non-NULL it must be a PyFileObject. In this case there
** is no readahead but in stead a flag is used to skip a following
** \n on the next read. Also, if the file is open in binary mode
** the whole conversion is skipped. Finally, the routine keeps track of
** the different types of newlines seen.
** The fobj parameter exists solely for legacy reasons and must be NULL.
** Note that we need no error handling: fgets() treats error and eof
** identically.
*/
Expand All @@ -254,32 +248,22 @@ Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
{
char *p = buf;
int c;
int newlinetypes = 0;
int skipnextlf = 0;

if (fobj) {
errno = ENXIO; /* What can you do... */
return NULL;
}
FLOCKFILE(stream);
c = 'x'; /* Shut up gcc warning */
while (--n > 0 && (c = GETC(stream)) != EOF ) {
if (skipnextlf ) {
if (skipnextlf) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block never executes. skipnextlf is only set if c == '\r' in the next block, in which case c is set to '\n', and the execution flow breaks out of the loop via if (c == '\n') break. The value of skipnextlf is handled after the loop. The loop can be simplified as follows:

    while (--n > 0 && (c = GETC(stream)) != EOF) {
        if (c == '\r') {
            /* Translate \r to \n, and skip an adjacent \n, if any. */
            skipnextlf = 1;
            c = '\n';
        }
        *p++ = c;
        if (c == '\n') {
            break;
        }
    }

skipnextlf = 0;
if (c == '\n') {
/* Seeing a \n here with skipnextlf true
** means we saw a \r before.
*/
newlinetypes |= NEWLINE_CRLF;
c = GETC(stream);
if (c == EOF) break;
} else {
/*
** Note that c == EOF also brings us here,
** so we're okay if the last char in the file
** is a CR.
*/
newlinetypes |= NEWLINE_CR;
}
}
if (c == '\r') {
Expand All @@ -289,26 +273,15 @@ Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
*/
skipnextlf = 1;
c = '\n';
} else if ( c == '\n') {
newlinetypes |= NEWLINE_LF;
}
*p++ = c;
if (c == '\n') break;
}
/* if ( c == EOF && skipnextlf )
newlinetypes |= NEWLINE_CR; */
FUNLOCKFILE(stream);
*p = '\0';
if ( skipnextlf ) {
/* If we have no file object we cannot save the
** skipnextlf flag. We have to readahead, which
** will cause a pause if we're reading from an
** interactive stream, but that is very unlikely
** unless we're doing something silly like
** exec(open("/dev/tty").read()).
*/
c = GETC(stream);
if ( c != '\n' )
if (skipnextlf) {
int c = GETC(stream);
if (c != '\n')
ungetc(c, stream);
}
if (p == buf)
Expand Down
0