common: add generic tokenization code

This is a little cleaner than passing around strings which are parsed
incrementally.
This commit is contained in:
2018-07-22 16:18:32 -07:00
parent 66539071de
commit 5a5ccafbb4
2 changed files with 83 additions and 0 deletions

View File

@@ -1,5 +1,6 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.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;
}
}

View File

@@ -16,6 +16,11 @@
*/
void downcase(char *str);
struct tokens;
struct tokens* tokenize(const char *string, const char *delims);
char *token_next(struct tokens* tokens);
#ifdef DEBUG
#define DEBUG_ON 1
#else