Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Johnston <jjohnstn@redhat.com>2004-09-23 01:22:07 +0400
committerJeff Johnston <jjohnstn@redhat.com>2004-09-23 01:22:07 +0400
commit602de582680a23990c59abde8347417a67196425 (patch)
treeac4cc69d269b366e250e7703be4bdaea865ffc72
parent71de40144754bbc705bd7ee9e8e1a2bf05df2c44 (diff)
2004-09-22 Jeff Johnston <jjohnstn@redhat.com>
* libc/stdio/fread.c (fread): For non-space-optimized case, add special code for unbuffered files to use user buffer and only require one low-level system read.
-rw-r--r--newlib/ChangeLog6
-rw-r--r--newlib/libc/stdio/fread.c93
2 files changed, 81 insertions, 18 deletions
diff --git a/newlib/ChangeLog b/newlib/ChangeLog
index 22a132145..1d4de3c9f 100644
--- a/newlib/ChangeLog
+++ b/newlib/ChangeLog
@@ -1,3 +1,9 @@
+2004-09-22 Jeff Johnston <jjohnstn@redhat.com>
+
+ * libc/stdio/fread.c (fread): For non-space-optimized case,
+ add special code for unbuffered files to use user buffer and
+ only require one low-level system read.
+
2004-09-21 Ian Lance Taylor <ian@wasabisystems.com>
* libc/machine/xscale/setjmp.S: New file, copied from
diff --git a/newlib/libc/stdio/fread.c b/newlib/libc/stdio/fread.c
index d8ceb8666..9a074dd4f 100644
--- a/newlib/libc/stdio/fread.c
+++ b/newlib/libc/stdio/fread.c
@@ -130,30 +130,87 @@ _DEFUN(fread, (buf, size, count, fp),
total = resid;
p = buf;
- while (resid > (r = fp->_r))
+#if !defined(PREFER_SIZE_OVER_SPEED) && !defined(__OPTIMIZE_SIZE__)
+
+ /* Optimize unbuffered I/O. */
+ if (fp->_flags & __SNBF)
+ {
+ /* First copy any available characters from ungetc buffer. */
+ int copy_size = resid > fp->_r ? fp->_r : resid;
+ _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) copy_size);
+ fp->_p += copy_size;
+ fp->_r -= copy_size;
+ p += copy_size;
+ resid -= copy_size;
+
+ /* If still more data needed, free any allocated ungetc buffer. */
+ if (HASUB (fp) && resid > 0)
+ FREEUB (fp);
+
+ /* Finally read directly into user's buffer if needed. */
+ if (resid > 0)
+ {
+ int rc = 0;
+ /* save fp buffering state */
+ void *old_base = fp->_bf._base;
+ void * old_p = fp->_p;
+ int old_size = fp->_bf._size;
+ /* allow __refill to use user's buffer */
+ fp->_bf._base = p;
+ fp->_bf._size = resid;
+ fp->_p = p;
+ rc = __srefill (fp);
+ /* restore fp buffering back to original state */
+ resid -= fp->_r;
+ fp->_r = 0;
+ fp->_bf._base = old_base;
+ fp->_bf._size = old_size;
+ fp->_p = old_p;
+ if (rc)
+ {
+ /* no more input: return partial result */
+#ifdef __SCLE
+ if (fp->_flags & __SCLE)
+ {
+ _funlockfile (fp);
+ return crlf (fp, buf, total-resid, 1) / size;
+ }
+#endif
+ _funlockfile (fp);
+ return (total - resid) / size;
+ }
+ }
+ }
+ else
+#endif /* !PREFER_SIZE_OVER_SPEED && !__OPTIMIZE_SIZE__ */
{
- _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r);
- fp->_p += r;
- /* fp->_r = 0 ... done in __srefill */
- p += r;
- resid -= r;
- if (__srefill (fp))
+ while (resid > (r = fp->_r))
{
- /* no more input: return partial result */
+ _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, (size_t) r);
+ fp->_p += r;
+ /* fp->_r = 0 ... done in __srefill */
+ p += r;
+ resid -= r;
+ if (__srefill (fp))
+ {
+ /* no more input: return partial result */
#ifdef __SCLE
- if (fp->_flags & __SCLE)
- {
- _funlockfile (fp);
- return crlf (fp, buf, total-resid, 1) / size;
- }
+ if (fp->_flags & __SCLE)
+ {
+ _funlockfile (fp);
+ return crlf (fp, buf, total-resid, 1) / size;
+ }
#endif
- _funlockfile (fp);
- return (total - resid) / size;
+ _funlockfile (fp);
+ return (total - resid) / size;
+ }
}
+ _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid);
+ fp->_r -= resid;
+ fp->_p += resid;
}
- _CAST_VOID memcpy ((_PTR) p, (_PTR) fp->_p, resid);
- fp->_r -= resid;
- fp->_p += resid;
+
+ /* Perform any CR/LF clean-up if necessary. */
#ifdef __SCLE
if (fp->_flags & __SCLE)
{