GRASS 8 Programmer's Manual 8.6.0dev(2026)-56a9afeb9f
Loading...
Searching...
No Matches
gis/token.c
Go to the documentation of this file.
1/*!
2 \file lib/gis/token.c
3
4 \brief GIS Library - Tokenize strings
5
6 (C) 2001-2008, 2011-2013 by the GRASS Development Team
7
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
10
11 \author USA CERL and others
12 */
13
14#include <stdlib.h>
15#include <string.h>
16#include <grass/gis.h>
17#include <grass/glocale.h>
18
19static char **tokenize(const char *, const char *, const char *);
20
21/*!
22 \brief Tokenize string
23
24 Given a string, <em>buf</em>, turn delimiter, <em>delim</em>, into
25 '\0' (NULL) and place pointers to tokens in tokens. <em>buf</em>
26 must not contain a new line (\n). <em>delim</em> may consist of more
27 than one character. G_free_tokens() must be called when finished
28 with tokens to release memory.
29
30 Example:
31 \code
32 char **tokens;
33 int ntok, i;
34 tokens = G_tokenize(buf, " |:,");
35 ntok = G_number_of_tokens(tokens);
36 for (i=0; i < ntok; i++) {
37 G_debug(1, "%d=[%s]", i, tokens[i]);
38 }
39 G_free_tokens(tokens);
40 \endcode
41
42 \param buf input string
43 \param delim string delimiter
44
45 \return pointer to string token
46 */
47char **G_tokenize(const char *buf, const char *delim)
48{
49 return tokenize(buf, delim, NULL);
50}
51
52/*!
53 \brief Tokenize string
54
55 This function behaves similarly to G_tokenize().
56
57 It introduces <em>valchar</em> which defines borders of token. Within
58 token <em>delim</em> is ignored.
59
60 Example:
61 \code
62 char *str = "a,'b,c',d";
63
64 char **tokens1, **tokens2;
65 int ntok1, ntok2;
66
67 tokens1 = G_tokenize(str, ",");
68 ntok1 = G_number_of_tokens(tokens1);
69
70 tokens1 = G_tokenize2(str, ",", "'");
71 ntok2 = G_number_of_tokens(tokens2);
72 \endcode
73
74 In this example <em>ntok1</em> will be 4, <em>ntok2</em> only 3,
75 i.e. { "a", "'b, c'", "d"}
76
77 \param buf input string
78 \param delim string delimiter
79 \param valchar character defining border of token
80
81 \return pointer to string token
82 */
83char **G_tokenize2(const char *buf, const char *delim, const char *valchar)
84{
85 return tokenize(buf, delim, valchar);
86}
87
88char **tokenize(const char *buf, const char *delim, const char *inchar)
89{
90 int i;
91 char **tokens;
92 const char *p;
93 char *q;
94 enum {
95 S_START,
98 };
100 int state;
101 int quo = inchar ? *inchar : -1;
102
103 /* do not modify buf, make a copy */
104 p = q = G_store(buf);
105
106 i = 0;
107 tokens = (char **)G_malloc(2 * sizeof(char *));
108
109 /* always one token */
110 tokens[i++] = q;
111
112 for (state = S_START;; p++) {
113 int c = *p;
114 int action = A_NO_OP;
115
116 switch (state) {
117 case S_START:
118 if (c == quo)
120 else if (c == '\0')
121 action = A_END_RECORD;
122 else if (strchr(delim, c))
123 action = A_NEW_FIELD;
124 else
125 action = A_ADD_CHAR;
126 break;
127 case S_IN_QUOTE:
128 if (c == quo)
130 else if (c == '\0')
131 action = A_ERROR;
132 else
133 action = A_ADD_CHAR;
134 break;
135 case S_AFTER_QUOTE:
136 if (c == quo)
137 state = S_IN_QUOTE, action = A_ADD_CHAR;
138 else if (c == '\0')
139 action = A_END_RECORD;
140 else if (strchr(delim, c))
141 state = S_START, action = A_NEW_FIELD;
142 else
143 action = A_ERROR;
144 break;
145 }
146
147 switch (action) {
148 case A_NO_OP:
149 break;
150 case A_ADD_CHAR:
151 *q++ = *p;
152 break;
153 case A_NEW_FIELD:
154 *q++ = '\0';
155 tokens[i++] = q;
156 tokens = G_realloc(tokens, (i + 2) * sizeof(char *));
157 break;
158 case A_END_RECORD:
159 *q++ = '\0';
160 tokens[i++] = NULL;
161 return tokens;
162 case A_ERROR:
163 G_warning(_("parse error"));
164 *q++ = '\0';
165 tokens[i++] = NULL;
166 return tokens;
167 }
168 }
169}
170
171/*!
172 \brief Return number of tokens
173
174 \param tokens
175
176 \return number of tokens
177 */
179{
180 int n;
181
182 n = 0;
183 for (n = 0; tokens[n] != NULL; n++)
184 ;
185
186 return n;
187}
188
189/*!
190 \brief Free memory allocated to tokens.
191
192 <b>Note:</b> <i>G_free_tokens()</i> must be called when finished with
193 tokens to release memory.
194
195 \param[out] tokens
196 */
198{
199 if (tokens[0] != NULL)
200 G_free(tokens[0]);
201 G_free(tokens);
202}
#define NULL
Definition ccmath.h:32
void G_free(void *)
Free allocated memory.
Definition gis/alloc.c:147
#define G_realloc(p, n)
Definition defs/gis.h:141
void G_warning(const char *,...) __attribute__((format(printf
#define G_malloc(n)
Definition defs/gis.h:139
char * G_store(const char *)
Copy string to allocated memory.
Definition strings.c:87
char ** G_tokenize2(const char *buf, const char *delim, const char *valchar)
Tokenize string.
Definition gis/token.c:83
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition gis/token.c:197
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
Definition gis/token.c:47
int G_number_of_tokens(char **tokens)
Return number of tokens.
Definition gis/token.c:178
#define _(str)
Definition glocale.h:10
struct state state
Definition parser.c:103