GRASS GIS 7 Programmer's Manual  7.0.3(2016)-r00000
token.c
Go to the documentation of this file.
1 
15 #include <stdlib.h>
16 #include <string.h>
17 #include <grass/gis.h>
18 #include <grass/glocale.h>
19 
20 static char **tokenize(const char *, const char *, const char *);
21 
48 char **G_tokenize(const char *buf, const char *delim)
49 {
50  return tokenize(buf, delim, NULL);
51 }
52 
84 char **G_tokenize2(const char *buf, const char *delim, const char *valchar)
85 {
86  return tokenize(buf, delim, valchar);
87 }
88 
89 char **tokenize(const char *buf, const char *delim, const char *inchar)
90 {
91  int i;
92  char **tokens;
93  const char *p;
94  char *q;
95  enum {
96  S_START,
97  S_IN_QUOTE,
98  S_AFTER_QUOTE,
99  };
100  enum {
101  A_NO_OP,
102  A_ADD_CHAR,
103  A_NEW_FIELD,
104  A_END_RECORD,
105  A_ERROR
106  };
107  int state;
108  int quo = inchar ? *inchar : -1;
109 
110  /* do not modify buf, make a copy */
111  p = q = G_store(buf);
112 
113  i = 0;
114  tokens = (char **)G_malloc(2 * sizeof(char *));
115 
116  /* always one token */
117  tokens[i++] = q;
118 
119  for (state = S_START; ; p++) {
120  int c = *p;
121  int action = A_NO_OP;
122  switch (state) {
123  case S_START:
124  if (c == quo)
125  state = S_IN_QUOTE;
126  else if (c == '\0')
127  action = A_END_RECORD;
128  else if (strchr(delim, c))
129  action = A_NEW_FIELD;
130  else
131  action = A_ADD_CHAR;
132  break;
133  case S_IN_QUOTE:
134  if (c == quo)
135  state = S_AFTER_QUOTE;
136  else if (c == '\0')
137  action = A_ERROR;
138  else
139  action = A_ADD_CHAR;
140  break;
141  case S_AFTER_QUOTE:
142  if (c == quo)
143  state = S_IN_QUOTE, action = A_ADD_CHAR;
144  else if (c == '\0')
145  action = A_END_RECORD;
146  else if (strchr(delim, c))
147  state = S_START, action = A_NEW_FIELD;
148  else
149  action = A_ERROR;
150  break;
151  }
152 
153  switch (action) {
154  case A_NO_OP:
155  break;
156  case A_ADD_CHAR:
157  *q++ = *p;
158  break;
159  case A_NEW_FIELD:
160  *q++ = '\0';
161  tokens[i++] = q;
162  tokens = G_realloc(tokens, (i + 2) * sizeof(char *));
163  break;
164  case A_END_RECORD:
165  *q++ = '\0';
166  tokens[i++] = NULL;
167  return tokens;
168  case A_ERROR:
169  G_warning(_("parse error"));
170  *q++ = '\0';
171  tokens[i++] = NULL;
172  return tokens;
173  }
174  }
175 }
176 
185 int G_number_of_tokens(char **tokens)
186 {
187  int n;
188 
189  n = 0;
190  for (n = 0; tokens[n] != NULL; n++)
191  ;
192 
193  return n;
194 }
195 
204 void G_free_tokens(char **tokens)
205 {
206  if (tokens[0] != NULL)
207  G_free(tokens[0]);
208  G_free(tokens);
209 }
char * G_store(const char *s)
Copy string to allocated memory.
Definition: strings.c:86
#define NULL
Definition: ccmath.h:32
int G_number_of_tokens(char **tokens)
Return number of tokens.
Definition: token.c:185
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition: token.c:204
char ** G_tokenize2(const char *buf, const char *delim, const char *valchar)
Tokenize string.
Definition: token.c:84
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
Definition: token.c:48
void G_free(void *buf)
Free allocated memory.
Definition: alloc.c:149
struct state state
Definition: parser.c:100
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition: gis/error.c:203