diff --git a/bench_str.csv b/bench_str.csv index 84a882c..e1184d3 100644 --- a/bench_str.csv +++ b/bench_str.csv @@ -479,3 +479,7 @@ 1400820886,12274457.34,2393445.83,55188.21 1400820922,12218386.22,2604565.56,77672.30 1400820933,12443155.46,2361317.46,45590.26 +1400829105,12110496.08,4797414.85,38479.85 +1400829117,12258758.55,4129968.45,59074.70 +1400829143,12339827.27,4775224.01,55924.05 +1400831278,11421287.15,4742488.93,39945.75 diff --git a/src/node.c b/src/node.c index aa2299c..63c38d3 100644 --- a/src/node.c +++ b/src/node.c @@ -3,9 +3,7 @@ #include #include #include - -// Jemalloc memory management -// #include +#include // PCRE #include @@ -160,8 +158,13 @@ void r3_tree_compile_patterns(node * n) { p++; edge *e = NULL; + int opcode_cnt = 0; for ( int i = 0 ; i < n->edge_len ; i++ ) { e = n->edges[i]; + + if ( e->opcode ) + opcode_cnt++; + if ( e->has_slug ) { // compile "foo/{slug}" to "foo/[^/]+" char * slug_pat = slug_compile(e->pattern, e->pattern_len); @@ -183,16 +186,15 @@ void r3_tree_compile_patterns(node * n) { info("pattern: %s\n",cpat); // if all edges use opcode, we should skip the combined_pattern. - /* if ( opcode_cnt == n->edge_len ) { - zfree(cpat); - return; + // zfree(cpat); + n->compare_type = NODE_COMPARE_OPCODE; + } else { + n->compare_type = NODE_COMPARE_PCRE; } - */ n->combined_pattern = cpat; - const char *error; int erroffset; unsigned int option_bits = 0; @@ -258,6 +260,47 @@ node * r3_tree_matchl(const node * n, char * path, int path_len, match_entry * e int rc; int i; int ov_cnt; + int restlen; + + if (n->compare_type == NODE_COMPARE_OPCODE ) { + for (i = 0; i < n->edge_len ; i++ ) { + char *pp = path; + char *pp_end = path + path_len; + e = n->edges[i]; + switch(e->opcode) { + case OP_EXPECT_NOSLASH: + while (*pp != '/' && pp < pp_end) { + pp++; + } + break; + case OP_EXPECT_DIGITS: + while ( isdigit(*pp) && pp < pp_end) { + pp++; + } + break; + case OP_EXPECT_WORDS: + while ( (isdigit(*pp) || isalpha(*pp)) && pp < pp_end) { + pp++; + } + break; + case OP_EXPECT_NODASH: + while (*pp != '-' && pp < pp_end) { + pp++; + } + break; + } + if ( (pp - path) > 0) { + restlen = pp_end - pp; + if (entry) { + str_array_append(entry->vars , zstrndup(path, pp - path)); + } + if (restlen == 0) { + return e->child && e->child->endpoint > 0 ? e->child : NULL; + } + return r3_tree_matchl(e->child, pp, pp_end - pp, entry); + } + } + } // if the pcre_pattern is found, and the pointer is not NULL, then it's // pcre pattern node, we use pcre_exec to match the nodes @@ -301,7 +344,7 @@ node * r3_tree_matchl(const node * n, char * path, int path_len, match_entry * e // info("%2d: %.*s\n", i, substring_length, substring_start); if ( substring_length > 0) { - int restlen = path_len - ov[1]; // fully match to the end + restlen = path_len - ov[1]; // fully match to the end // info("matched item => restlen:%d edges:%d i:%d\n", restlen, n->edge_len, i); e = n->edges[i - 1]; @@ -322,7 +365,7 @@ node * r3_tree_matchl(const node * n, char * path, int path_len, match_entry * e } if ( (e = r3_node_find_edge_str(n, path, path_len)) != NULL ) { - int restlen = path_len - e->pattern_len; + restlen = path_len - e->pattern_len; if (restlen == 0) { return e->child && e->child->endpoint > 0 ? e->child : NULL; } diff --git a/tests/check_tree.c b/tests/check_tree.c index 91706f1..8f88139 100644 --- a/tests/check_tree.c +++ b/tests/check_tree.c @@ -42,22 +42,25 @@ START_TEST (test_r3_node_find_edge) END_TEST -START_TEST (test_compile) -{ - str_array *t; +static node * create_simple_str_tree() { node * n; n = r3_tree_create(10); - - - node *m; - edge *e ; - r3_tree_insert_path(n, "/zoo", NULL); r3_tree_insert_path(n, "/foo", NULL); r3_tree_insert_path(n, "/bar", NULL); r3_tree_compile(n); - fail_if( n->combined_pattern ); - fail_if( NULL == r3_node_find_edge_str(n, "/", strlen("/") ) ); + return n; +} + + + +START_TEST (test_compile) +{ + str_array *t; + node * n = create_simple_str_tree(); + + node *m; + edge *e ; #ifdef DEBUG r3_tree_dump(n, 0);