[prev in list] [next in list] [prev in thread] [next in thread] 

List:       uclibc
Subject:    [PATCH 2/2] stdio: make getdelim faster
From:       rep.dot.nop () gmail ! com (Bernhard Reutner-Fischer)
Date:       2011-10-06 13:40:53
Message-ID: 1317908453-26055-3-git-send-email-rep.dot.nop () gmail ! com
[Download RAW message or body]

by speeding up fgets_unlocked: Avoid doing char IO.

Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop at gmail.com>
---
 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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic