1 /* readtokens.c -- Functions for reading tokens from an input stream.
2 Copyright (C) 1990-1991, 1999-2004 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
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. */
28 #include "readtokens.h"
35 #include "unlocked-io.h"
38 #define STREQ(a,b) ((a) == (b) || ((a) && (b) && *(a) == *(b) \
39 && strcmp(a, b) == 0))
41 /* Initialize a tokenbuffer. */
44 init_tokenbuffer (token_buffer *tokenbuffer)
46 tokenbuffer->size = 0;
47 tokenbuffer->buffer = NULL;
50 /* Read a token from STREAM into TOKENBUFFER.
51 A token is delimited by any of the N_DELIM bytes in DELIM.
52 Upon return, the token is in tokenbuffer->buffer and
53 has a trailing '\0' instead of any original delimiter.
54 The function value is the length of the token not including
55 the final '\0'. Upon EOF (i.e. on the call after the last
56 token is read) or error, return -1 without modifying tokenbuffer.
57 The EOF and error conditions may be distinguished in the caller
58 by testing ferror (STREAM).
60 This function works properly on lines containing NUL bytes
61 and on files do not end with a delimiter. */
64 readtoken (FILE *stream,
67 token_buffer *tokenbuffer)
72 static const char *saved_delim = NULL;
73 static char isdelim[256];
76 if (delim == NULL && saved_delim == NULL)
79 same_delimiters = false;
80 if (delim != saved_delim && saved_delim != NULL)
82 same_delimiters = true;
83 for (i = 0; i < n_delim; i++)
85 if (delim[i] != saved_delim[i])
87 same_delimiters = false;
97 memset (isdelim, 0, sizeof isdelim);
98 for (j = 0; j < n_delim; j++)
100 unsigned char ch = delim[j];
105 /* FIXME: don't fool with this caching. Use strchr instead. */
106 /* skip over any leading delimiters */
107 for (c = getc (stream); c >= 0 && isdelim[c]; c = getc (stream))
112 p = tokenbuffer->buffer;
113 n = tokenbuffer->size;
121 p = x2nrealloc (p, &n, sizeof *p);
137 tokenbuffer->buffer = p;
138 tokenbuffer->size = n;
142 /* Build a NULL-terminated array of pointers to tokens
143 read from STREAM. Return the number of tokens read.
144 All storage is obtained through calls to xmalloc-like functions.
146 %%% Question: is it worth it to do a single
147 %%% realloc() of `tokens' just before returning? */
150 readtokens (FILE *stream,
151 size_t projected_n_tokens,
155 size_t **token_lengths)
157 token_buffer tb, *token = &tb;
163 if (projected_n_tokens == 0)
164 projected_n_tokens = 64;
166 projected_n_tokens++; /* add one for trailing NULL pointer */
168 sz = projected_n_tokens;
169 tokens = xnmalloc (sz, sizeof *tokens);
170 lengths = xnmalloc (sz, sizeof *lengths);
173 init_tokenbuffer (token);
177 size_t token_length = readtoken (stream, delim, n_delim, token);
180 tokens = x2nrealloc (tokens, &sz, sizeof *tokens);
181 lengths = xnrealloc (lengths, sz, sizeof *lengths);
184 if (token_length == (size_t) -1)
186 /* don't increment n_tokens for NULL entry */
187 tokens[n_tokens] = NULL;
188 lengths[n_tokens] = 0;
191 tmp = xnmalloc (token_length + 1, sizeof *tmp);
192 lengths[n_tokens] = token_length;
193 tokens[n_tokens] = memcpy (tmp, token->buffer, token_length + 1);
197 free (token->buffer);
198 *tokens_out = tokens;
199 if (token_lengths != NULL)
200 *token_lengths = lengths;