Loading...
Searching...
No Matches
token.c
Go to the documentation of this file.
/*!
\file lib/gis/token.c
\brief GIS Library - Tokenize strings
(C) 2001-2008, 2011-2013 by the GRASS Development Team
This program is free software under the GNU General Public License
(>=v2). Read the file COPYING that comes with GRASS for details.
\author USA CERL and others
*/
#include <stdlib.h>
#include <string.h>
#include <grass/gis.h>
#include <grass/glocale.h>
static char **tokenize(const char *, const char *, const char *);
/*!
\brief Tokenize string
Given a string, <em>buf</em>, turn delimiter, <em>delim</em>, into
'\0' (NULL) and place pointers to tokens in tokens. <em>buf</em>
must not contain a new line (\n). <em>delim</em> may consist of more
than one character. G_free_tokens() must be called when finished
with tokens to release memory.
Example:
\code
char **tokens;
int ntok, i;
tokens = G_tokenize(buf, " |:,");
ntok = G_number_of_tokens(tokens);
for (i=0; i < ntok; i++) {
G_debug(1, "%d=[%s]", i, tokens[i]);
}
G_free_tokens(tokens);
\endcode
\param buf input string
\param delim string delimiter
\return pointer to string token
*/
char **G_tokenize(const char *buf, const char *delim)
{
return tokenize(buf, delim, NULL);
}
/*!
\brief Tokenize string
This function behaves similarly to G_tokenize().
It introduces <em>valchar</em> which defines borders of token. Within
token <em>delim</em> is ignored.
Example:
\code
char *str = "a,'b,c',d";
char **tokens1, **tokens2;
int ntok1, ntok2;
tokens1 = G_tokenize(str, ",");
ntok1 = G_number_of_tokens(tokens1);
tokens1 = G_tokenize2(str, ",", "'");
ntok2 = G_number_of_tokens(tokens2);
\endcode
In this example <em>ntok1</em> will be 4, <em>ntok2</em> only 3,
i.e. { "a", "'b, c'", "d"}
\param buf input string
\param delim string delimiter
\param valchar character defining border of token
\return pointer to string token
*/
char **G_tokenize2(const char *buf, const char *delim, const char *valchar)
{
return tokenize(buf, delim, valchar);
}
char **tokenize(const char *buf, const char *delim, const char *inchar)
{
int i;
char **tokens;
const char *p;
char *q;
enum {
S_START,
S_IN_QUOTE,
S_AFTER_QUOTE,
};
enum { A_NO_OP, A_ADD_CHAR, A_NEW_FIELD, A_END_RECORD, A_ERROR };
int state;
int quo = inchar ? *inchar : -1;
/* do not modify buf, make a copy */
p = q = G_store(buf);
i = 0;
tokens = (char **)G_malloc(2 * sizeof(char *));
/* always one token */
tokens[i++] = q;
for (state = S_START;; p++) {
int c = *p;
int action = A_NO_OP;
switch (state) {
case S_START:
if (c == quo)
state = S_IN_QUOTE;
else if (c == '\0')
action = A_END_RECORD;
else if (strchr(delim, c))
action = A_NEW_FIELD;
else
action = A_ADD_CHAR;
break;
case S_IN_QUOTE:
if (c == quo)
state = S_AFTER_QUOTE;
else if (c == '\0')
action = A_ERROR;
else
action = A_ADD_CHAR;
break;
case S_AFTER_QUOTE:
if (c == quo)
state = S_IN_QUOTE, action = A_ADD_CHAR;
else if (c == '\0')
action = A_END_RECORD;
else if (strchr(delim, c))
state = S_START, action = A_NEW_FIELD;
else
action = A_ERROR;
break;
}
switch (action) {
case A_NO_OP:
break;
case A_ADD_CHAR:
*q++ = *p;
break;
case A_NEW_FIELD:
*q++ = '\0';
tokens[i++] = q;
tokens = G_realloc(tokens, (i + 2) * sizeof(char *));
break;
case A_END_RECORD:
*q++ = '\0';
tokens[i++] = NULL;
return tokens;
case A_ERROR:
G_warning(_("parse error"));
*q++ = '\0';
tokens[i++] = NULL;
return tokens;
}
}
}
/*!
\brief Return number of tokens
\param tokens
\return number of tokens
*/
int G_number_of_tokens(char **tokens)
{
int n;
n = 0;
for (n = 0; tokens[n] != NULL; n++)
;
return n;
}
/*!
\brief Free memory allocated to tokens.
<b>Note:</b> <i>G_free_tokens()</i> must be called when finished with
tokens to release memory.
\param[out] tokens
*/
void G_free_tokens(char **tokens)
{
if (tokens[0] != NULL)
G_free(tokens[0]);
G_free(tokens);
}
G_free
void G_free(void *buf)
Free allocated memory.
Definition alloc.c:147
NULL
#define NULL
Definition ccmath.h:32
G_warning
void G_warning(const char *msg,...)
Print a warning message to stderr.
Definition gis/error.c:203
G_store
char * G_store(const char *s)
Copy string to allocated memory.
Definition strings.c:87
G_tokenize2
char ** G_tokenize2(const char *buf, const char *delim, const char *valchar)
Tokenize string.
Definition token.c:83
G_free_tokens
void G_free_tokens(char **tokens)
Free memory allocated to tokens.
Definition token.c:197
G_tokenize
char ** G_tokenize(const char *buf, const char *delim)
Tokenize string.
Definition token.c:47
G_number_of_tokens
int G_number_of_tokens(char **tokens)
Return number of tokens.
Definition token.c:178