Author: Brian Kearns <[email protected]>
Branch: use-file-star-for-file
Changeset: r73495:a92bdb7b7707
Date: 2014-09-11 19:26 -0400
http://bitbucket.org/pypy/pypy/changeset/a92bdb7b7707/

Log:    prefer getc_unlocked over fgets in readline

diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -100,6 +100,9 @@
     c_flockfile = lambda ll_file: None
     c_funlockfile = lambda ll_file: None
     c_getc_unlocked = c_getc
+    USE_FGETS_IN_GETLINE = True
+else:
+    USE_FGETS_IN_GETLINE = False
 
 c_fgets = llexternal('fgets', [rffi.CCHARP, rffi.INT, FILEP], rffi.CCHARP)
 c_fread = llexternal('fread', [rffi.CCHARP, rffi.SIZE_T, rffi.SIZE_T, FILEP],
@@ -435,7 +438,7 @@
             rffi.keep_buffer_alive_until_here(raw_buf, gc_buf)
         return s.build()
 
-    def _readline1(self, raw_buf):
+    def _get_line_fgets_single(self, raw_buf):
         ll_file = self._ll_file
         for i in range(BASE_LINE_SIZE):
             raw_buf[i] = '\n'
@@ -470,97 +473,103 @@
             assert p > 0 and raw_buf[p - 1] == '\0'
             return p - 1
 
+    def _get_line_fgets(self):
+        with rffi.scoped_alloc_buffer(BASE_LINE_SIZE) as buf:
+            c = self._get_line_fgets_single(buf.raw)
+            if c >= 0:
+                return buf.str(c)
+
+            # this is the rare case: the line is longer than BASE_LINE_SIZE
+            s = StringBuilder()
+            while True:
+                s.append_charpsize(buf.raw, BASE_LINE_SIZE - 1)
+                c = self._get_line_fgets_single(buf.raw)
+                if c >= 0:
+                    break
+            s.append_charpsize(buf.raw, c)
+        return s.build()
+
+    def _get_line(self, size):
+        if USE_FGETS_IN_GETLINE and size < 0 and not self._univ_newline:
+            return self._get_line_fgets()
+
+        ll_file = self._ll_file
+        newlinetypes = self._newlinetypes
+        skipnextlf = self._skipnextlf
+        c = 0
+        s = StringBuilder()
+        while True:
+            c_flockfile(ll_file)
+            if self._univ_newline:
+                while size < 0 or s.getlength() < size:
+                    c = c_getc_unlocked(ll_file)
+                    if c == EOF:
+                        break
+                    if skipnextlf:
+                        skipnextlf = False
+                        if c == ord('\n'):
+                            newlinetypes |= NEWLINE_CRLF
+                            c = c_getc_unlocked(ll_file)
+                            if c == EOF:
+                                break
+                        else:
+                            newlinetypes |= NEWLINE_CR
+                    if c == ord('\r'):
+                        skipnextlf = True
+                        c = ord('\n')
+                    elif c == ord('\n'):
+                        newlinetypes |= NEWLINE_LF
+                    s.append(chr(c))
+                    if c == ord('\n'):
+                        break
+                if c == EOF:
+                    if c_ferror(ll_file) and rposix.get_errno() == errno.EINTR:
+                        c_funlockfile(ll_file)
+                        self._newlinetypes = newlinetypes
+                        self._skipnextlf = skipnextlf
+                        if self._signal_checker is not None:
+                            self._signal_checker()
+                        c_clearerr(ll_file)
+                        continue
+                    if skipnextlf:
+                        newlinetypes |= NEWLINE_CR
+            else:
+                while size < 0 or s.getlength() < size:
+                    c = c_getc_unlocked(ll_file)
+                    if c == EOF:
+                        break
+                    s.append(chr(c))
+                    if c == ord('\n'):
+                        break
+            c_funlockfile(ll_file)
+            self._newlinetypes = newlinetypes
+            self._skipnextlf = skipnextlf
+            if c == ord('\n'):
+                break
+            elif c == EOF:
+                if c_ferror(ll_file):
+                    if rposix.get_errno() == errno.EINTR:
+                        if self._signal_checker is not None:
+                            self._signal_checker()
+                        c_clearerr(ll_file)
+                        continue
+                    c_clearerr(ll_file)
+                    raise _from_errno(IOError)
+                c_clearerr(ll_file)
+                if self._signal_checker is not None:
+                    self._signal_checker()
+                break
+            else:
+                assert s.getlength() == size
+                break
+        return s.build()
+
     def readline(self, size=-1):
         self._check_closed()
         self._check_readable()
         if size == 0:
             return ""
-        elif size < 0 and not self._univ_newline:
-            with rffi.scoped_alloc_buffer(BASE_LINE_SIZE) as buf:
-                c = self._readline1(buf.raw)
-                if c >= 0:
-                    return buf.str(c)
-
-                # this is the rare case: the line is longer than BASE_LINE_SIZE
-                s = StringBuilder()
-                while True:
-                    s.append_charpsize(buf.raw, BASE_LINE_SIZE - 1)
-                    c = self._readline1(buf.raw)
-                    if c >= 0:
-                        break
-                s.append_charpsize(buf.raw, c)
-            return s.build()
-        else:  # size > 0 or self._univ_newline
-            ll_file = self._ll_file
-            newlinetypes = self._newlinetypes
-            skipnextlf = self._skipnextlf
-            c = 0
-            s = StringBuilder()
-            while True:
-                c_flockfile(ll_file)
-                if self._univ_newline:
-                    while size < 0 or s.getlength() < size:
-                        c = c_getc_unlocked(ll_file)
-                        if c == EOF:
-                            break
-                        if skipnextlf:
-                            skipnextlf = False
-                            if c == ord('\n'):
-                                newlinetypes |= NEWLINE_CRLF
-                                c = c_getc_unlocked(ll_file)
-                                if c == EOF:
-                                    break
-                            else:
-                                newlinetypes |= NEWLINE_CR
-                        if c == ord('\r'):
-                            skipnextlf = True
-                            c = ord('\n')
-                        elif c == ord('\n'):
-                            newlinetypes |= NEWLINE_LF
-                        s.append(chr(c))
-                        if c == ord('\n'):
-                            break
-                    if c == EOF:
-                        if c_ferror(ll_file) and rposix.get_errno() == 
errno.EINTR:
-                            c_funlockfile(ll_file)
-                            self._newlinetypes = newlinetypes
-                            self._skipnextlf = skipnextlf
-                            if self._signal_checker is not None:
-                                self._signal_checker()
-                            c_clearerr(ll_file)
-                            continue
-                        if skipnextlf:
-                            newlinetypes |= NEWLINE_CR
-                else:
-                    while s.getlength() < size:
-                        c = c_getc_unlocked(ll_file)
-                        if c == EOF:
-                            break
-                        s.append(chr(c))
-                        if c == ord('\n'):
-                            break
-                c_funlockfile(ll_file)
-                self._newlinetypes = newlinetypes
-                self._skipnextlf = skipnextlf
-                if c == ord('\n'):
-                    break
-                elif c == EOF:
-                    if c_ferror(ll_file):
-                        if rposix.get_errno() == errno.EINTR:
-                            if self._signal_checker is not None:
-                                self._signal_checker()
-                            c_clearerr(ll_file)
-                            continue
-                        c_clearerr(ll_file)
-                        raise _from_errno(IOError)
-                    c_clearerr(ll_file)
-                    if self._signal_checker is not None:
-                        self._signal_checker()
-                    break
-                else:
-                    assert s.getlength() == size
-                    break
-            return s.build()
+        return self._get_line(size)
 
     @enforceargs(None, str)
     def write(self, value):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to