[pypy-commit] pypy use-file-star-for-file: implement rfile read logic to match cpython
bdkearns
noreply at buildbot.pypy.org
Thu Sep 11 08:36:29 CEST 2014
Author: Brian Kearns <bdkearns at gmail.com>
Branch: use-file-star-for-file
Changeset: r73447:0c381d8d106c
Date: 2014-09-11 02:18 -0400
http://bitbucket.org/pypy/pypy/changeset/0c381d8d106c/
Log: implement rfile read logic to match cpython
diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -330,37 +330,49 @@
return i
def read(self, size=-1):
- # XXX CPython uses a more delicate logic here
self._check_closed()
ll_file = self._ll_file
- if size == 0:
- return ""
- elif size < 0:
- # read the entire contents
- buf = lltype.malloc(rffi.CCHARP.TO, BASE_BUF_SIZE, flavor='raw')
- try:
- s = StringBuilder()
- while True:
- returned_size = self._fread(buf, BASE_BUF_SIZE, ll_file)
- returned_size = intmask(returned_size) # is between 0 and BASE_BUF_SIZE
- if returned_size == 0:
- if c_feof(ll_file):
- # ok, finished
- return s.build()
- raise _error(ll_file)
- s.append_charpsize(buf, returned_size)
- finally:
- lltype.free(buf, flavor='raw')
- else: # size > 0
- with rffi.scoped_alloc_buffer(size) as buf:
- returned_size = self._fread(buf.raw, size, ll_file)
- returned_size = intmask(returned_size) # is between 0 and size
- if returned_size == 0:
- if not c_feof(ll_file):
- raise _error(ll_file)
- s = buf.str(returned_size)
- assert s is not None
- return s
+
+ bytesrequested = size
+ if bytesrequested < 0:
+ buffersize = BASE_BUF_SIZE
+ else:
+ buffersize = bytesrequested
+ bytesread = 0
+
+ s = StringBuilder()
+ buf = lltype.malloc(rffi.CCHARP.TO, buffersize, flavor='raw')
+ try:
+ while True:
+ if bytesrequested >= 0:
+ buffersize = bytesrequested - bytesread
+ assert buffersize >= 0
+ chunksize = intmask(self._fread(buf, buffersize, ll_file))
+ interrupted = (c_ferror(ll_file) and
+ rposix.get_errno() == errno.EINTR)
+ if interrupted:
+ c_clearerr(ll_file)
+ # XXX check signals
+ if chunksize == 0:
+ if interrupted:
+ continue
+ if not c_ferror(ll_file):
+ break
+ c_clearerr(ll_file)
+ if bytesread > 0 and rposix.get_errno() == errno.EAGAIN:
+ break
+ err = rposix.get_errno()
+ raise IOError(err, os.strerror(err))
+ s.append_charpsize(buf, chunksize)
+ bytesread += chunksize
+ if chunksize < buffersize and not interrupted:
+ c_clearerr(ll_file)
+ break
+ if bytesrequested >= 0:
+ break
+ finally:
+ lltype.free(buf, flavor='raw')
+ return s.build()
def _readline1(self, raw_buf):
ll_file = self._ll_file
More information about the pypy-commit
mailing list