1 /* readtokens.c -- Functions for reading tokens from an input stream.
3 Copyright (C) 1990-1991, 1999-2004, 2006 Free Software Foundation, Inc.
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 Written by Jim Meyering. */
20 /* This almost supercedes xreadline stuff -- using delim="\n"
21 gives the same functionality, except that these functions
22 would never return empty lines. */
26 #include "readtokens.h"
36 # include "unlocked-io.h"
39 #define STREQ(a,b) ((a) == (b) || ((a) && (b) && *(a) == *(b) \
40 && strcmp(a, b) == 0))
42 /* Initialize a tokenbuffer. */
45 init_tokenbuffer (token_buffer *tokenbuffer)
47 tokenbuffer->size = 0;
48 tokenbuffer->buffer = NULL;
51 /* Read a token from STREAM into TOKENBUFFER.
52 A token is delimited by any of the N_DELIM bytes in DELIM.
53 Upon return, the token is in tokenbuffer->buffer and
54 has a trailing '\0' instead of any original delimiter.
55 The function value is the length of the token not including
56 the final '\0'. Upon EOF (i.e. on the call after the last
57 token is read) or error, return -1 without modifying tokenbuffer.
58 The EOF and error conditions may be distinguished in the caller
59 by testing ferror (STREAM).
61 This function works properly on lines containing NUL bytes
62 and on files do not end with a delimiter. */
65 readtoken (FILE *stream,
68 token_buffer *tokenbuffer)
73 static const char *saved_delim = NULL;
74 static char isdelim[256];
77 if (delim == NULL && saved_delim == NULL)
80 same_delimiters = false;
81 if (delim != saved_delim && saved_delim != NULL)
83 same_delimiters = true;
84 for (i = 0; i < n_delim; i++)
86 if (delim[i] != saved_delim[i])
88 same_delimiters = false;
98 memset (isdelim, 0, sizeof isdelim);
99 for (j = 0; j < n_delim; j++)
101 unsigned char ch = delim[j];
106 /* FIXME: don't fool with this caching. Use strchr instead. */
107 /* skip over any leading delimiters */
108 for (c = getc (stream); c >= 0 && isdelim[c]; c = getc (stream))
113 p = tokenbuffer->buffer;
114 n = tokenbuffer->size;
122 p = x2nrealloc (p, &n, sizeof *p);
138 tokenbuffer->buffer = p;
139 tokenbuffer->size = n;
143 /* Build a NULL-terminated array of pointers to tokens
144 read from STREAM. Return the number of tokens read.
145 All storage is obtained through calls to xmalloc-like functions.
147 %%% Question: is it worth it to do a single
148 %%% realloc() of `tokens' just before returning? */
151 readtokens (FILE *stream,
152 size_t projected_n_tokens,
156 size_t **token_lengths)
158 token_buffer tb, *token = &tb;
164 if (projected_n_tokens == 0)
165 projected_n_tokens = 64;
167 projected_n_tokens++; /* add one for trailing NULL pointer */
169 sz = projected_n_tokens;
170 tokens = xnmalloc (sz, sizeof *tokens);
171 lengths = xnmalloc (sz, sizeof *lengths);
174 init_tokenbuffer (token);
178 size_t token_length = readtoken (stream, delim, n_delim, token);
181 tokens = x2nrealloc (tokens, &sz, sizeof *tokens);
182 lengths = xnrealloc (lengths, sz, sizeof *lengths);
185 if (token_length == (size_t) -1)
187 /* don't increment n_tokens for NULL entry */
188 tokens[n_tokens] = NULL;
189 lengths[n_tokens] = 0;
192 tmp = xnmalloc (token_length + 1, sizeof *tmp);
193 lengths[n_tokens] = token_length;
194 tokens[n_tokens] = memcpy (tmp, token->buffer, token_length + 1);
198 free (token->buffer);
199 *tokens_out = tokens;
200 if (token_lengths != NULL)
201 *token_lengths = lengths;