summaryrefslogtreecommitdiff
path: root/lib/readtokens.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/readtokens.c')
-rw-r--r--lib/readtokens.c137
1 files changed, 64 insertions, 73 deletions
diff --git a/lib/readtokens.c b/lib/readtokens.c
index 28aafa9..5933120 100644
--- a/lib/readtokens.c
+++ b/lib/readtokens.c
@@ -1,11 +1,12 @@
/* readtokens.c -- Functions for reading tokens from an input stream.
- Copyright (C) 1990-1991, 1999-2004, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1990-1991, 1999-2004, 2006, 2009-2016 Free Software
+ Foundation, Inc.
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,12 +14,11 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
Written by Jim Meyering. */
-/* This almost supercedes xreadline stuff -- using delim="\n"
+/* This almost supersedes xreadline stuff -- using delim="\n"
gives the same functionality, except that these functions
would never return empty lines. */
@@ -26,6 +26,7 @@
#include "readtokens.h"
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -37,9 +38,6 @@
# include "unlocked-io.h"
#endif
-#define STREQ(a,b) ((a) == (b) || ((a) && (b) && *(a) == *(b) \
- && strcmp(a, b) == 0))
-
/* Initialize a tokenbuffer. */
void
@@ -49,6 +47,22 @@ init_tokenbuffer (token_buffer *tokenbuffer)
tokenbuffer->buffer = NULL;
}
+typedef size_t word;
+enum { bits_per_word = sizeof (word) * CHAR_BIT };
+
+static bool
+get_nth_bit (size_t n, word const *bitset)
+{
+ return bitset[n / bits_per_word] >> n % bits_per_word & 1;
+}
+
+static void
+set_nth_bit (size_t n, word *bitset)
+{
+ size_t one = 1;
+ bitset[n / bits_per_word] |= one << n % bits_per_word;
+}
+
/* Read a token from STREAM into TOKENBUFFER.
A token is delimited by any of the N_DELIM bytes in DELIM.
Upon return, the token is in tokenbuffer->buffer and
@@ -60,53 +74,28 @@ init_tokenbuffer (token_buffer *tokenbuffer)
by testing ferror (STREAM).
This function works properly on lines containing NUL bytes
- and on files do not end with a delimiter. */
+ and on files that do not end with a delimiter. */
size_t
readtoken (FILE *stream,
- const char *delim,
- size_t n_delim,
- token_buffer *tokenbuffer)
+ const char *delim,
+ size_t n_delim,
+ token_buffer *tokenbuffer)
{
char *p;
int c;
size_t i, n;
- static const char *saved_delim = NULL;
- static char isdelim[256];
- bool same_delimiters;
-
- if (delim == NULL && saved_delim == NULL)
- abort ();
-
- same_delimiters = false;
- if (delim != saved_delim && saved_delim != NULL)
- {
- same_delimiters = true;
- for (i = 0; i < n_delim; i++)
- {
- if (delim[i] != saved_delim[i])
- {
- same_delimiters = false;
- break;
- }
- }
- }
+ word isdelim[(UCHAR_MAX + bits_per_word) / bits_per_word];
- if (!same_delimiters)
+ memset (isdelim, 0, sizeof isdelim);
+ for (i = 0; i < n_delim; i++)
{
- size_t j;
- saved_delim = delim;
- memset (isdelim, 0, sizeof isdelim);
- for (j = 0; j < n_delim; j++)
- {
- unsigned char ch = delim[j];
- isdelim[ch] = 1;
- }
+ unsigned char ch = delim[i];
+ set_nth_bit (ch, isdelim);
}
- /* FIXME: don't fool with this caching. Use strchr instead. */
/* skip over any leading delimiters */
- for (c = getc (stream); c >= 0 && isdelim[c]; c = getc (stream))
+ for (c = getc (stream); c >= 0 && get_nth_bit (c, isdelim); c = getc (stream))
{
/* empty */
}
@@ -117,21 +106,21 @@ readtoken (FILE *stream,
for (;;)
{
if (c < 0 && i == 0)
- return -1;
+ return -1;
if (i == n)
- p = x2nrealloc (p, &n, sizeof *p);
+ p = x2nrealloc (p, &n, sizeof *p);
if (c < 0)
- {
- p[i] = 0;
- break;
- }
- if (isdelim[c])
- {
- p[i] = 0;
- break;
- }
+ {
+ p[i] = 0;
+ break;
+ }
+ if (get_nth_bit (c, isdelim))
+ {
+ p[i] = 0;
+ break;
+ }
p[i++] = c;
c = getc (stream);
}
@@ -146,15 +135,15 @@ readtoken (FILE *stream,
All storage is obtained through calls to xmalloc-like functions.
%%% Question: is it worth it to do a single
- %%% realloc() of `tokens' just before returning? */
+ %%% realloc() of 'tokens' just before returning? */
size_t
readtokens (FILE *stream,
- size_t projected_n_tokens,
- const char *delim,
- size_t n_delim,
- char ***tokens_out,
- size_t **token_lengths)
+ size_t projected_n_tokens,
+ const char *delim,
+ size_t n_delim,
+ char ***tokens_out,
+ size_t **token_lengths)
{
token_buffer tb, *token = &tb;
char **tokens;
@@ -165,7 +154,7 @@ readtokens (FILE *stream,
if (projected_n_tokens == 0)
projected_n_tokens = 64;
else
- projected_n_tokens++; /* add one for trailing NULL pointer */
+ projected_n_tokens++; /* add one for trailing NULL pointer */
sz = projected_n_tokens;
tokens = xnmalloc (sz, sizeof *tokens);
@@ -178,18 +167,18 @@ readtokens (FILE *stream,
char *tmp;
size_t token_length = readtoken (stream, delim, n_delim, token);
if (n_tokens >= sz)
- {
- tokens = x2nrealloc (tokens, &sz, sizeof *tokens);
- lengths = xnrealloc (lengths, sz, sizeof *lengths);
- }
+ {
+ tokens = x2nrealloc (tokens, &sz, sizeof *tokens);
+ lengths = xnrealloc (lengths, sz, sizeof *lengths);
+ }
if (token_length == (size_t) -1)
- {
- /* don't increment n_tokens for NULL entry */
- tokens[n_tokens] = NULL;
- lengths[n_tokens] = 0;
- break;
- }
+ {
+ /* don't increment n_tokens for NULL entry */
+ tokens[n_tokens] = NULL;
+ lengths[n_tokens] = 0;
+ break;
+ }
tmp = xnmalloc (token_length + 1, sizeof *tmp);
lengths[n_tokens] = token_length;
tokens[n_tokens] = memcpy (tmp, token->buffer, token_length + 1);
@@ -200,5 +189,7 @@ readtokens (FILE *stream,
*tokens_out = tokens;
if (token_lengths != NULL)
*token_lengths = lengths;
+ else
+ free (lengths);
return n_tokens;
}