common: add generic tokenization code
This is a little cleaner than passing around strings which are parsed incrementally.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
|
|
||||||
@@ -31,3 +32,80 @@ void downcase(char *str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct tokens {
|
||||||
|
struct token *next;
|
||||||
|
char *old;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct token {
|
||||||
|
char *string;
|
||||||
|
struct token *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct tokens* tokenize(const char *string, const char *delims)
|
||||||
|
{
|
||||||
|
struct tokens *tokens = malloc(sizeof(*tokens));
|
||||||
|
struct token *token = malloc(sizeof(*token));
|
||||||
|
char *prev, *delim;
|
||||||
|
int done = 0;
|
||||||
|
|
||||||
|
tokens->next = token;
|
||||||
|
tokens->old = NULL;
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
char *delim = strpbrk(prev, delims);
|
||||||
|
int has_token = 0;
|
||||||
|
|
||||||
|
/* No remaining delims, is there a token left? */
|
||||||
|
if (delim == NULL) {
|
||||||
|
has_token = strlen(prev) > 0;
|
||||||
|
done = 1;
|
||||||
|
break;
|
||||||
|
} else if (delim - string == 1) {
|
||||||
|
/* Adjacent delimiters, skip them */
|
||||||
|
prev = delim;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
has_token = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (has_token) {
|
||||||
|
token->next = malloc(sizeof(struct tokens));
|
||||||
|
token->string = strndup(prev, delim - prev);
|
||||||
|
token = token->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tokens->next->string == NULL) {
|
||||||
|
free(tokens->next);
|
||||||
|
free(tokens);
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
free(token);
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char *token_next(struct tokens* tokens)
|
||||||
|
{
|
||||||
|
struct token *prev;
|
||||||
|
|
||||||
|
if (tokens->next) {
|
||||||
|
if (tokens->old) {
|
||||||
|
free(tokens->old);
|
||||||
|
}
|
||||||
|
tokens->old = tokens->next->string;
|
||||||
|
|
||||||
|
prev = tokens->next;
|
||||||
|
tokens->next = prev->next;
|
||||||
|
free(prev);
|
||||||
|
|
||||||
|
return tokens->old;
|
||||||
|
} else {
|
||||||
|
free(tokens->old);
|
||||||
|
free(tokens);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,11 @@
|
|||||||
*/
|
*/
|
||||||
void downcase(char *str);
|
void downcase(char *str);
|
||||||
|
|
||||||
|
struct tokens;
|
||||||
|
|
||||||
|
struct tokens* tokenize(const char *string, const char *delims);
|
||||||
|
char *token_next(struct tokens* tokens);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define DEBUG_ON 1
|
#define DEBUG_ON 1
|
||||||
#else
|
#else
|
||||||
|
|||||||
Reference in New Issue
Block a user