Mercurial > hg > octave-nkf > gnulib-hg
changeset 10019:e435c0a7bace
Optimize getndelim2 to use block operations when possible.
* modules/getndelim2 (Depends-on): Add stdbool, freadptr,
freadseek, and memchr2.
* lib/getndelim2.c (getndelim2): Use them for block reads.
Signed-off-by: Eric Blake <ebb9@byu.net>
author | Eric Blake <ebb9@byu.net> |
---|---|
date | Tue, 29 Apr 2008 11:59:35 -0600 |
parents | 8406478f0d13 |
children | a6cd3ce278f5 |
files | ChangeLog lib/getndelim2.c modules/getndelim2 |
diffstat | 3 files changed, 71 insertions(+), 19 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-04-29 Eric Blake <ebb9@byu.net> + + Optimize getndelim2 to use block operations when possible. + * modules/getndelim2 (Depends-on): Add stdbool, freadptr, + freadseek, and memchr2. + * lib/getndelim2.c (getndelim2): Use them for block reads. + 2008-04-29 Bruno Haible <bruno@clisp.org> * m4/inet_ntop.m4 (gl_INET_NTOP): Require gl_USE_SYSTEM_EXTENSIONS.
--- a/lib/getndelim2.c +++ b/lib/getndelim2.c @@ -23,8 +23,10 @@ #include "getndelim2.h" +#include <stdbool.h> +#include <stddef.h> #include <stdlib.h> -#include <stddef.h> +#include <string.h> #if USE_UNLOCKED_IO # include "unlocked-io.h" @@ -41,6 +43,10 @@ #include <limits.h> #include <stdint.h> +#include "freadptr.h" +#include "freadseek.h" +#include "memchr2.h" + #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif @@ -63,6 +69,7 @@ ssize_t bytes_stored = -1; char *ptr = *lineptr; size_t size = *linesize; + bool done = false; if (!ptr) { @@ -81,23 +88,62 @@ if (nbytes_avail == 0 && nmax <= size) goto done; + /* Normalize delimiters, since memchr2 doesn't handle EOF. */ + if (delim1 == EOF) + delim1 = delim2; + else if (delim2 == EOF) + delim2 = delim1; + flockfile (stream); - for (;;) + while (!done) { /* Here always ptr + size == read_pos + nbytes_avail. */ int c; + const char *buffer; + size_t buffer_len; + + buffer = freadptr (stream, &buffer_len); + if (buffer) + { + if (delim1 != EOF) + { + const char *end = memchr2 (buffer, delim1, delim2, buffer_len); + if (end) + { + buffer_len = end - buffer + 1; + done = true; + } + } + } + else + { + c = getc (stream); + if (c == EOF) + { + /* Return partial line, if any. */ + if (read_pos == ptr) + goto unlock_done; + else + break; + } + if (c == delim1 || c == delim2) + done = true; + buffer_len = 1; + } /* We always want at least one byte left in the buffer, since we always (unless we get an error while reading the first byte) NUL-terminate the line buffer. */ - if (nbytes_avail < 2 && size < nmax) + if (nbytes_avail < 1 + buffer_len && size < nmax) { size_t newsize = size < MIN_CHUNK ? size + MIN_CHUNK : 2 * size; char *newptr; + if (newsize < buffer_len) + newsize = buffer_len + size; if (! (size < newsize && newsize <= nmax)) newsize = nmax; @@ -118,25 +164,20 @@ read_pos = size - nbytes_avail + ptr; } - c = getc (stream); - if (c == EOF) + if (1 < nbytes_avail) { - /* Return partial line, if any. */ - if (read_pos == ptr) - goto unlock_done; + size_t copy_len = nbytes_avail - 1; + if (buffer_len < copy_len) + copy_len = buffer_len; + if (buffer) + memcpy (read_pos, buffer, copy_len); else - break; + *read_pos = c; + read_pos += copy_len; + nbytes_avail -= copy_len; } - - if (nbytes_avail >= 2) - { - *read_pos++ = c; - nbytes_avail--; - } - - if (c == delim1 || c == delim2) - /* Return the line. */ - break; + if (buffer && freadseek (stream, buffer_len)) + goto unlock_done; } /* Done - NUL terminate and return the number of bytes read.