[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