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