From b6ac95ff4c5f791ce6af7d8dce016e72ea9d32d5 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Wed, 2 Sep 2015 22:20:59 -0400 Subject: [PATCH] [read performance iterate] parse-trie iterate --- c/containers/parse_trie.c | 69 ++++++++++++++++++++++++++-------- c/containers/parse_trie.h | 2 +- c/containers/test_parse_trie.c | 44 +++++++++++++++++----- 3 files changed, 89 insertions(+), 26 deletions(-) diff --git a/c/containers/parse_trie.c b/c/containers/parse_trie.c index 31fbafd60..f2e754f03 100644 --- a/c/containers/parse_trie.c +++ b/c/containers/parse_trie.c @@ -1,21 +1,27 @@ #include +#include #include "lib/mlrutil.h" #include "containers/parse_trie.h" -static parse_trie_node_t* parse_trie_node_alloc(); +static parse_trie_node_t* parse_trie_node_alloc(char c); static void parse_trie_print_aux(parse_trie_node_t* pnode, int depth); +static void parse_trie_add_string_aux(parse_trie_node_t* pnode, char* string, int stridx, int len); // ---------------------------------------------------------------- parse_trie_t* parse_trie_alloc() { parse_trie_t* ptrie = mlr_malloc_or_die(sizeof(parse_trie_t)); + ptrie->proot = parse_trie_node_alloc(0); + ptrie->maxlen = 0; return ptrie; } -static parse_trie_node_t* parse_trie_node_alloc() { +static parse_trie_node_t* parse_trie_node_alloc(char c) { parse_trie_node_t* pnode = mlr_malloc_or_die(sizeof(parse_trie_node_t)); for (int i = 0; i < 256; i++) pnode->pnexts[i] = NULL; - pnode->c = 0; + pnode->c = c; + pnode->stridx = -1; + pnode->strlen = -1; return pnode; } @@ -35,33 +41,62 @@ void parse_trie_print(parse_trie_t* ptrie) { } static void parse_trie_print_aux(parse_trie_node_t* pnode, int depth) { - printf("[pnode=%p]\n", pnode); for (int i = 0; i < depth; i++) printf(" "); - printf("c=%c,stridx=%d,strlen=%d\n", pnode->c, pnode->stridx, pnode->strlen); - printf("[pnode=%p]\n", pnode); + printf("c=%c[%02x],stridx=%d,strlen=%d\n", + isprint((unsigned char)pnode->c) ? pnode->c : '?', + (unsigned)pnode->c, + pnode->stridx, + pnode->strlen); for (int i = 0; i < 256; i++) { parse_trie_node_t* pnext = pnode->pnexts[i]; if (pnext != NULL) { parse_trie_print_aux(pnext, depth+1); + } else { + //printf("c=%c[%02x],stridx=%d,strlen=%d\n", + //isprint((unsigned char)pnode->c) ? pnode->c : '?', + //(unsigned)pnode->c, + //pnode->stridx, + //pnode->strlen); } } } // ---------------------------------------------------------------- -void parse_trie_add_string(parse_trie_t* ptrie, char* string) { - if (ptrie->proot == NULL) { - ptrie->proot = parse_trie_node_alloc(); +void parse_trie_add_string(parse_trie_t* ptrie, char* string, int stridx) { + int len = strlen(string); + parse_trie_add_string_aux(ptrie->proot, string, stridx, strlen(string)); + if (len > ptrie->maxlen) + ptrie->maxlen = len; +} + +static void parse_trie_add_string_aux(parse_trie_node_t* pnode, char* string, int stridx, int len) { + char c = string[0]; + if (c == 0) { + pnode->stridx = stridx; + pnode->strlen = len; + } else { + parse_trie_node_t* pnext = pnode->pnexts[(unsigned)c]; + if (pnext == NULL) { + pnext = parse_trie_node_alloc(c); + pnext->c = c; + pnext->stridx = -1; + pnext->strlen = -1; + pnode->pnexts[(unsigned)c] = pnext; + } + parse_trie_add_string_aux(pnext, &string[1], stridx, len); } - //parse_trie_node_t* pnode = ptrie->proot; - return; // xxx stub } // ---------------------------------------------------------------- -// Example: +// Example input: // * string 0 is "a" // * string 1 is "aa" // * buf is "aaabc" +// Output: +// * return value is TRUE +// * stridx is 1 since longest match is "aa" +// * matchlen is 2 since "aa" has length 2 int parse_trie_match(parse_trie_t* ptrie, char* buf, int buflen, int* pstridx, int* pmatchlen) { parse_trie_node_t* pnode = ptrie->proot; parse_trie_node_t* pnext; @@ -69,10 +104,14 @@ int parse_trie_match(parse_trie_t* ptrie, char* buf, int buflen, int* pstridx, i for (i = 0; i < buflen; i++) { char c = buf[i]; pnext = pnode->pnexts[(unsigned) c]; - // xxx not quite right - if (pnode == NULL) + if (pnext == NULL) return FALSE; + if (pnext->strlen > 0) { + *pstridx = pnext->stridx; + *pmatchlen = pnext->strlen; + return TRUE; + } pnode = pnext; } - return TRUE; // xxx stub + return FALSE; } diff --git a/c/containers/parse_trie.h b/c/containers/parse_trie.h index e252f41f6..cd7eba67d 100644 --- a/c/containers/parse_trie.h +++ b/c/containers/parse_trie.h @@ -20,7 +20,7 @@ typedef struct _parse_trie_t { parse_trie_t* parse_trie_alloc(); void parse_trie_free(parse_trie_t* ptrie); void parse_trie_print(parse_trie_t* ptrie); -void parse_trie_add_string(parse_trie_t* ptrie, char* string); +void parse_trie_add_string(parse_trie_t* ptrie, char* string, int stridx); int parse_trie_match(parse_trie_t* ptrie, char* buf, int buflen, int* pstridx, int* pmatchlen); #endif // PARSE_TRIE_H diff --git a/c/containers/test_parse_trie.c b/c/containers/test_parse_trie.c index 899eca5f6..aeedd59f6 100644 --- a/c/containers/test_parse_trie.c +++ b/c/containers/test_parse_trie.c @@ -11,15 +11,38 @@ int assertions_run = 0; int assertions_failed = 0; // ---------------------------------------------------------------- -static char * test_disjoint() { +static char * test_simplest() { parse_trie_t* ptrie = parse_trie_alloc(); - parse_trie_add_string(ptrie, "abc"); - parse_trie_add_string(ptrie, "fg"); + parse_trie_print(ptrie); + parse_trie_add_string(ptrie, "a", 0); parse_trie_print(ptrie); int stridx = -2; int matchlen = -2; - int rc = parse_trie_match(ptrie, "abcde", 2, &stridx, &matchlen); + int rc = parse_trie_match(ptrie, "a", 1, &stridx, &matchlen); + mu_assert_lf(rc == TRUE); + mu_assert_lf(stridx == 0); + mu_assert_lf(matchlen == 1); + + parse_trie_free(ptrie); + return 0; +} + +// ---------------------------------------------------------------- +static char * test_disjoint() { + parse_trie_t* ptrie = parse_trie_alloc(); + parse_trie_print(ptrie); + parse_trie_add_string(ptrie, "abc", 0); + parse_trie_print(ptrie); + parse_trie_add_string(ptrie, "fg", 1); + parse_trie_print(ptrie); + + int stridx = -2; + int matchlen = -2; + int rc = parse_trie_match(ptrie, "abcde", 5, &stridx, &matchlen); + printf("rc = %d\n", rc); + printf("stridx = %d\n", stridx); + printf("matchlen = %d\n", matchlen); mu_assert_lf(rc == TRUE); mu_assert_lf(stridx == 0); mu_assert_lf(matchlen == 3); @@ -31,12 +54,12 @@ static char * test_disjoint() { // ---------------------------------------------------------------- static char * test_short_long() { parse_trie_t* ptrie = parse_trie_alloc(); - parse_trie_add_string(ptrie, "a"); - parse_trie_add_string(ptrie, "aa"); + parse_trie_add_string(ptrie, "a", 0); + parse_trie_add_string(ptrie, "aa", 1); int stridx = -2; int matchlen = -2; - int rc = parse_trie_match(ptrie, "aaabc", 2, &stridx, &matchlen); + int rc = parse_trie_match(ptrie, "aaabc", 5, &stridx, &matchlen); mu_assert_lf(rc == TRUE); mu_assert_lf(stridx == 0); mu_assert_lf(matchlen == 3); @@ -48,12 +71,12 @@ static char * test_short_long() { // ---------------------------------------------------------------- static char * test_long_short() { parse_trie_t* ptrie = parse_trie_alloc(); - parse_trie_add_string(ptrie, "aa"); - parse_trie_add_string(ptrie, "a"); + parse_trie_add_string(ptrie, "aa", 0); + parse_trie_add_string(ptrie, "a", 1); int stridx = -2; int matchlen = -2; - int rc = parse_trie_match(ptrie, "aaabc", 2, &stridx, &matchlen); + int rc = parse_trie_match(ptrie, "aaabc", 5, &stridx, &matchlen); mu_assert_lf(rc == TRUE); mu_assert_lf(stridx == 0); mu_assert_lf(matchlen == 3); @@ -64,6 +87,7 @@ static char * test_long_short() { // ================================================================ static char * all_tests() { + mu_run_test(test_simplest); mu_run_test(test_disjoint); mu_run_test(test_short_long); mu_run_test(test_long_short);