by speeding up fgets_unlocked: Avoid doing char IO.

Signed-off-by: Bernhard Reutner-Fischer <[email protected]>
---
 libc/stdio/_stdio.h   |    6 ++++++
 libc/stdio/fgets.c    |   36 ++++++++++++++++++++++++++++--------
 libc/stdio/getdelim.c |   46 +++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 77 insertions(+), 11 deletions(-)

diff --git a/libc/stdio/_stdio.h b/libc/stdio/_stdio.h
index ec98f9e..3642ce5 100644
--- a/libc/stdio/_stdio.h
+++ b/libc/stdio/_stdio.h
@@ -333,6 +333,10 @@ extern int __stdio_trans2w_o(FILE *__restrict stream, int 
oflag) attribute_hidde
 /* Valid when reading... */
 #define __STDIO_STREAM_BUFFER_RAVAIL(S)                ((S)->__bufread - 
(S)->__bufpos)
 #define __STDIO_STREAM_BUFFER_GET(S)           (*(S)->__bufpos++)
+#define __STDIO_STREAM_CAN_USE_BUFFER_GET_N(S, N) \
+       ((S)->__bufpos + N <= (S)->__bufread)
+#define __STDIO_STREAM_BUFFER_GET_N(S, N)      (__extension__({ \
+                       }))
 #define __STDIO_FILL_READ_BUFFER(S)            __stdio_rfill((S))
 
 #define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S)          \
@@ -368,7 +372,9 @@ extern int __stdio_trans2w_o(FILE *__restrict stream, int 
oflag) attribute_hidde
 #define __STDIO_STREAM_IS_NARROW_FBF(S)                                (0)
 
 #define __STDIO_STREAM_BUFFER_RAVAIL(S)                                (0)
+#define __STDIO_STREAM_CAN_USE_BUFFER_GET_N(S, N)   (0)
 #define __STDIO_STREAM_BUFFER_GET(S)                           (EOF)
+#define __STDIO_STREAM_BUFFER_GET_N(S, N)                      (EOF)
 #define __STDIO_FILL_READ_BUFFER(S)                            (0)
 #define __STDIO_STREAM_INIT_BUFREAD_BUFPOS(S)                  ((void)0)
 
diff --git a/libc/stdio/fgets.c b/libc/stdio/fgets.c
index bc710c7..22b0ecb 100644
--- a/libc/stdio/fgets.c
+++ b/libc/stdio/fgets.c
@@ -14,8 +14,7 @@
 char *fgets_unlocked(char *__restrict s, int n,
                                           register FILE * __restrict stream)
 {
-       register char *p;
-       int c;
+       char *p;
 
        __STDIO_STREAM_VALIDATE(stream);
 
@@ -30,12 +29,31 @@ char *fgets_unlocked(char *__restrict s, int n,
 
        p = s;
 
-       while (--n) {
-               if (__STDIO_STREAM_CAN_USE_BUFFER_GET(stream)) {
-                       if ((*p++ = __STDIO_STREAM_BUFFER_GET(stream)) == '\n') 
{
-                               break;
-                       }
-               } else {
+       while (n) {
+               if (__STDIO_STREAM_CAN_USE_BUFFER_GET_N(stream, n)) {
+                       //TODO: make that __STDIO_STREAM_BUFFER_GET_N(stream, n)
+                       size_t len;
+                       unsigned char *pdelim;
+                       pdelim = (unsigned 
char*)memchr((void*)stream->__bufpos, '\n', n);
+                       len = pdelim
+                               ? pdelim - stream->__bufpos + 1
+                               : n;
+                       memcpy(p, stream->__bufpos, len);
+                       stream->__bufpos += len;
+                       p += len;
+                       break;
+               } else if (__STDIO_STREAM_IS_NARROW_READING(stream)
+                                  || !__STDIO_STREAM_TRANS_TO_READ(stream, 
__FLAG_NARROW)) {
+                       size_t ravail;
+                       __STDIO_STREAM_DISABLE_GETC(stream);
+                       ravail = __STDIO_FILL_READ_BUFFER(stream);
+                       if (ravail)
+                               __STDIO_STREAM_ENABLE_GETC(stream); /* FBF or 
LBF */
+                       n = ravail;
+               }
+#ifndef __STDIO_BUFFERS
+               else {
+                       int c;
                        if ((c = __fgetc_unlocked(stream)) == EOF) {
                                if (__FERROR_UNLOCKED(stream)) {
                                        goto ERROR;
@@ -45,7 +63,9 @@ char *fgets_unlocked(char *__restrict s, int n,
                        if ((*p++ = c) == '\n') {
                                break;
                        }
+                       --n;
                }
+#endif
        }
 
 #ifdef __UCLIBC_MJN3_ONLY__
diff --git a/libc/stdio/getdelim.c b/libc/stdio/getdelim.c
index c264b32..982946a 100644
--- a/libc/stdio/getdelim.c
+++ b/libc/stdio/getdelim.c
@@ -23,14 +23,16 @@
  * a reading.  So space may be allocated even if initially at EOF.
  */
 
-#define GETDELIM_GROWBY                64
+#ifndef __STDIO_BUFFERS
+# define GETDELIM_GROWBY               64
+#endif
 
 ssize_t getdelim(char **__restrict lineptr, size_t *__restrict n,
                                   int delimiter, register FILE *__restrict 
stream)
 {
        register char *buf;
        ssize_t pos = -1;
-       int ch;
+
        __STDIO_AUTO_THREADLOCK_VAR;
 
        if (!lineptr || !n || !stream) { /* Be compatable with glibc... even */
@@ -42,6 +44,43 @@ ssize_t getdelim(char **__restrict lineptr, size_t 
*__restrict n,
                        *n = 0;         /* ignore value passed and treat size 
as 0. */
                }
 
+#ifdef __STDIO_BUFFERS
+               pos = 0;
+               do {
+                       char *pdelim;
+                       char *chp;
+                       ssize_t len = __STDIO_STREAM_BUFFER_RAVAIL(stream);
+                       const unsigned fill = len == 0;
+                       if (len < 1)
+                               /* Somebody might have called setvbuf, so not 
__STDIO_BUFSIZ */
+                               len = __STDIO_STREAM_BUFFER_SIZE(stream);
+                       while ((size_t)pos + len > *n) { /* if is sufficient, 
but well.. */
+                               *n += 2 * __STDIO_STREAM_BUFFER_SIZE(stream);
+                               if (!(buf = realloc(buf, *n))) {
+                                       pos = -1;
+                                       break;
+                               }
+                               *lineptr = buf;
+                       }
+                       if ((chp = fgets_unlocked(buf + pos, len, stream))) {
+                               const unsigned r = 
__STDIO_STREAM_BUFFER_RAVAIL(stream);
+                               len -= r ? r : fill ? 
__STDIO_STREAM_BUFFER_WAVAIL(stream) : 0;
+                               pdelim = (char*) memchr((void*)chp, delimiter, 
len);
+                               pos += pdelim
+                                       ? pdelim - chp + 1
+                                       : len;
+                               if (pdelim) {
+                                       *(++pdelim) = '\0';
+                                       break;
+                               }
+                       } else {
+                               if (!pos)
+                                       pos = -1;
+                               break;
+                       }
+               } while (1);
+
+#else
                /* Within the loop, pos is actually the current buffer index + 
2,
                 * because we want to make sure we have enough space to store
                 * an additional char plus a nul terminator.
@@ -49,6 +88,7 @@ ssize_t getdelim(char **__restrict lineptr, size_t 
*__restrict n,
                pos = 1;
 
                do {
+                       int ch;
                        if ((size_t)pos >= *n) {
                                if (!(buf = realloc(buf, *n += 
GETDELIM_GROWBY))) {
                                        pos = -1;
@@ -71,7 +111,7 @@ ssize_t getdelim(char **__restrict lineptr, size_t 
*__restrict n,
                        break;
 
                } while (1);
-
+#endif
                __STDIO_AUTO_THREADUNLOCK(stream);
        }
 
-- 
1.7.6.3

_______________________________________________
uClibc mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/uclibc

Reply via email to