Line data Source code
1 : /* readtokens0.c -- Read NUL-separated tokens from an input stream.
2 :
3 : Copyright (C) 2004, 2006 Free Software Foundation, Inc.
4 :
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.
9 :
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.
14 :
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/>.
17 :
18 : Written by Jim Meyering. */
19 :
20 : #include <config.h>
21 :
22 : #include <stdlib.h>
23 :
24 : #include "readtokens0.h"
25 :
26 : #define obstack_chunk_alloc malloc
27 : #define obstack_chunk_free free
28 :
29 : void
30 3 : readtokens0_init (struct Tokens *t)
31 : {
32 3 : t->n_tok = 0;
33 3 : t->tok = NULL;
34 3 : t->tok_len = NULL;
35 3 : obstack_init (&t->o_data);
36 3 : obstack_init (&t->o_tok);
37 3 : obstack_init (&t->o_tok_len);
38 3 : }
39 :
40 : void
41 0 : readtokens0_free (struct Tokens *t)
42 : {
43 0 : obstack_free (&t->o_data, NULL);
44 0 : obstack_free (&t->o_tok, NULL);
45 0 : obstack_free (&t->o_tok_len, NULL);
46 0 : }
47 :
48 : /* Finalize (in the obstack_finish sense) the current token
49 : and record its pointer and length. */
50 : static void
51 8 : save_token (struct Tokens *t)
52 : {
53 : /* Don't count the trailing NUL byte in the length. */
54 8 : size_t len = obstack_object_size (&t->o_data) - 1;
55 8 : char const *s = obstack_finish (&t->o_data);
56 8 : obstack_ptr_grow (&t->o_tok, s);
57 8 : obstack_grow (&t->o_tok_len, &len, sizeof len);
58 8 : t->n_tok++;
59 8 : }
60 :
61 : /* Read NUL-separated tokens from stream IN into T until EOF or error.
62 : The final NUL is optional. Always append a NULL pointer to the
63 : resulting list of token pointers, but that pointer isn't counted
64 : via t->n_tok. Return true if successful. */
65 : bool
66 12 : readtokens0 (FILE *in, struct Tokens *t)
67 : {
68 :
69 : while (1)
70 9 : {
71 12 : int c = fgetc (in);
72 12 : if (c == EOF)
73 : {
74 3 : size_t len = obstack_object_size (&t->o_data);
75 : /* If the current object has nonzero length, then there
76 : was no NUL byte at EOF -- or maybe there was an error,
77 : in which case, we need to append a NUL byte to our buffer. */
78 3 : if (len)
79 : {
80 1 : obstack_1grow (&t->o_data, '\0');
81 1 : save_token (t);
82 : }
83 :
84 3 : break;
85 : }
86 :
87 9 : obstack_1grow (&t->o_data, c);
88 9 : if (c == '\0')
89 7 : save_token (t);
90 : }
91 :
92 : /* Add a NULL pointer at the end, in case the caller (like du)
93 : requires an argv-style array of strings. */
94 3 : obstack_ptr_grow (&t->o_tok, NULL);
95 :
96 3 : t->tok = obstack_finish (&t->o_tok);
97 3 : t->tok_len = obstack_finish (&t->o_tok_len);
98 3 : return ! ferror (in);
99 : }
|