END_TEST START_TEST (test_pcre_patterns_insert) { node * n = r3_tree_create(10); // r3_tree_insert_path(n, "/foo-{user}-{id}", NULL, NULL); // r3_tree_dump(n, 0); r3_tree_insert_path(n, "/post/{handle:\\d+}-{id:\\d+}", NULL); r3_tree_compile(n); r3_tree_dump(n, 0); node *matched; matched = r3_tree_matchl(n, "/post/111-222", strlen("/post/111-222"), NULL); ck_assert(matched); ck_assert_int_gt(matched->endpoint, 0); // incomplete string shouldn't match matched = r3_tree_matchl(n, "/post/111-", strlen("/post/111-"), NULL); ck_assert(matched); ck_assert_int_eq(matched->endpoint, 0); r3_tree_free(n); }
END_TEST START_TEST(test_pcre_pattern_more) { match_entry * entry; entry = match_entry_createl( "/user/123" , strlen("/user/123") ); node * n = r3_tree_create(10); int var0 = 5; int var1 = 100; int var2 = 200; int var3 = 300; info("var0: %p\n", &var0); info("var1: %p\n", &var1); info("var2: %p\n", &var2); info("var3: %p\n", &var3); r3_tree_insert_path(n, "/user/{id:\\d+}", &var1); r3_tree_insert_path(n, "/user2/{id:\\d+}", &var2); r3_tree_insert_path(n, "/user3/{id:\\d{3}}", &var3); r3_tree_insert_path(n, "/user", &var0); r3_tree_compile(n, NULL); r3_tree_dump(n, 0); node *matched; matched = r3_tree_matchl(n, "/user/123", strlen("/user/123"), entry); ck_assert(matched); ck_assert(entry->vars->len > 0); ck_assert_str_eq(entry->vars->tokens[0],"123"); info("matched %p\n", matched->data); info("matched %p\n", matched->data); ck_assert_int_eq( *((int*) matched->data), var1); matched = r3_tree_matchl(n, "/user2/123", strlen("/user2/123"), entry); ck_assert(matched); ck_assert(entry->vars->len > 0); ck_assert_str_eq(entry->vars->tokens[0],"123"); ck_assert_int_eq( *((int*)matched->data), var2); matched = r3_tree_matchl(n, "/user3/123", strlen("/user3/123"), entry); ck_assert(matched); ck_assert(entry->vars->len > 0); ck_assert_str_eq(entry->vars->tokens[0],"123"); ck_assert_int_eq( *((int*)matched->data), var3); r3_tree_free(n); }
END_TEST START_TEST (test_pcre_patterns_insert) { node * n = r3_tree_create(10); // r3_tree_insert_path(n, "/foo-{user}-{id}", NULL, NULL); r3_tree_insert_path(n, "/post/{handle:\\d+}-{id:\\d+}", NULL); r3_tree_insert_path(n, "/post/foo", NULL); r3_tree_insert_path(n, "/post/bar", NULL); char *errstr = NULL; int errcode; errcode = r3_tree_compile(n, &errstr); ck_assert(errcode == 0); // no error // r3_tree_dump(n, 0); node *matched; matched = r3_tree_match(n, "/post/foo", NULL); ck_assert(matched); ck_assert(matched->endpoint > 0); matched = r3_tree_match(n, "/post/bar", NULL); ck_assert(matched); ck_assert(matched->endpoint > 0); matched = r3_tree_match(n, "/post/kkkfoo", NULL); ck_assert(!matched); matched = r3_tree_match(n, "/post/kkkbar", NULL); ck_assert(!matched); matched = r3_tree_matchl(n, "/post/111-222", strlen("/post/111-222"), NULL); ck_assert(matched); ck_assert(matched->endpoint > 0); // incomplete string shouldn't match matched = r3_tree_matchl(n, "/post/111-", strlen("/post/111-"), NULL); ck_assert(! matched); r3_tree_free(n); }
END_TEST START_TEST(test_pcre_pattern_simple) { match_entry * entry; entry = match_entry_createl( "/user/123" , strlen("/user/123") ); node * n = r3_tree_create(10); r3_tree_insert_path(n, "/user/{id:\\d+}", NULL); r3_tree_insert_path(n, "/user", NULL); r3_tree_compile(n); // r3_tree_dump(n, 0); node *matched; matched = r3_tree_matchl(n, "/user/123", strlen("/user/123"), entry); fail_if(matched == NULL); ck_assert_int_gt(entry->vars->len, 0); ck_assert_str_eq(entry->vars->tokens[0],"123"); }
/** * This function matches the URL path and return the left node * * r3_tree_matchl returns NULL when the path does not match. returns *node when the path matches. * * @param node n the root of the tree * @param char* path the URL path to dispatch * @param int path_len the length of the URL path. * @param match_entry* entry match_entry is used for saving the captured dynamic strings from pcre result. */ node * r3_tree_matchl(const node * n, const char * path, int path_len, const match_entry * entry) { info("try matching: %s\n", path); edge *e; unsigned short i; unsigned short restlen; if (n->compare_type == NODE_COMPARE_OPCODE) { char *pp; const char *pp_end = path + path_len; for (i = 0; i < n->edge_len ; i++ ) { pp = (char*) path; e = n->edges[i]; switch(e->opcode) { case OP_EXPECT_NOSLASH: while (*pp != '/' && pp < pp_end) pp++; break; case OP_EXPECT_MORE_ALPHA: while ( isalpha(*pp) && pp < pp_end) pp++; break; case OP_EXPECT_MORE_DIGITS: while ( isdigit(*pp) && pp < pp_end) pp++; break; case OP_EXPECT_MORE_WORDS: while ( (isdigit(*pp) || isalpha(*pp)) && pp < pp_end) pp++; break; case OP_EXPECT_NODASH: while (*pp != '-' && pp < pp_end) pp++; break; } // check match 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 if (n->pcre_pattern) { char *substring_start = NULL; int substring_length = 0; int ov[ n->ov_cnt ]; char rc; info("pcre matching %s on %s\n", n->combined_pattern, path); rc = pcre_exec( n->pcre_pattern, /* the compiled pattern */ n->pcre_extra, path, /* the subject string */ path_len, /* the length of the subject */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ov, /* output vector for substring information */ n->ov_cnt); /* number of elements in the output vector */ // does not match all edges, return NULL; if (rc < 0) { #ifdef DEBUG printf("pcre rc: %d\n", rc ); switch(rc) { case PCRE_ERROR_NOMATCH: printf("pcre: no match '%s' on pattern '%s'\n", path, n->combined_pattern); break; // Handle other special cases if you like default: printf("pcre matching error '%d' '%s' on pattern '%s'\n", rc, path, n->combined_pattern); break; } #endif return NULL; } for (i = 1; i < rc; i++) { substring_start = ((char*) path) + ov[2*i]; substring_length = ov[2*i+1] - ov[2*i]; // info("%2d: %.*s\n", i, substring_length, substring_start); if ( substring_length > 0) { 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]; if (entry && e->has_slug) { // append captured token to entry str_array_append(entry->vars , zstrndup(substring_start, substring_length)); } if (restlen == 0 ) { return e->child && e->child->endpoint > 0 ? e->child : NULL; } // get the length of orginal string: $0 return r3_tree_matchl( e->child, path + (ov[1] - ov[0]), restlen, entry); } } // does not match return NULL; } if ( (e = r3_node_find_edge_str(n, path, path_len)) != NULL ) { restlen = path_len - e->pattern_len; if (restlen == 0) { return e->child && e->child->endpoint > 0 ? e->child : NULL; } return r3_tree_matchl(e->child, path + e->pattern_len, restlen, entry); } return NULL; }
/** * This function matches the URL path and return the left node * * r3_tree_matchl returns NULL when the path does not match. returns *node when the path matches. * * @param node n the root of the tree * @param char* path the URL path to dispatch * @param int path_len the length of the URL path. * @param match_entry* entry match_entry is used for saving the captured dynamic strings from pcre result. */ node * r3_tree_matchl(node * n, char * path, int path_len, match_entry * entry) { info("try matching: %s\n", path); edge *e; int rc; int i; // 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 if (n->pcre_pattern) { info("pcre matching %s on %s\n", n->combined_pattern, path); rc = pcre_exec( n->pcre_pattern, /* the compiled pattern */ // PCRE Study makes this slow NULL, // n->pcre_extra, /* no extra data - we didn't study the pattern */ path, /* the subject string */ path_len, /* the length of the subject */ 0, /* start at offset 0 in the subject */ 0, /* default options */ n->ov, /* output vector for substring information */ n->ov_cnt); /* number of elements in the output vector */ // info("rc: %d\n", rc ); if (rc < 0) { switch(rc) { case PCRE_ERROR_NOMATCH: printf("No match\n"); break; /* Handle other special cases if you like */ default: printf("Matching error %d\n", rc); break; } // does not match all edges, return NULL; return NULL; } for (i = 1; i < rc; i++) { char *substring_start = path + n->ov[2*i]; int substring_length = n->ov[2*i+1] - n->ov[2*i]; // info("%2d: %.*s\n", i, substring_length, substring_start); if ( substring_length > 0) { int restlen = path_len - n->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]; if (entry && e->has_slug) { // append captured token to entry str_array_append(entry->vars , strndup(substring_start, substring_length)); } if (restlen == 0) { return e->child; } // get the length of orginal string: $0 return r3_tree_matchl( e->child, path + (n->ov[1] - n->ov[0]), restlen, entry); } } // does not match return NULL; } if ( (e = r3_node_find_edge_str(n, path, path_len)) != NULL ) { int restlen = path_len - e->pattern_len; if(restlen > 0) { return r3_tree_matchl(e->child, path + e->pattern_len, restlen, entry); } return e->child; } return NULL; }
END_TEST START_TEST (test_compile) { str_array *t; 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("/") ) ); #ifdef DEBUG r3_tree_dump(n, 0); #endif r3_tree_insert_path(n, "/foo/{id}", NULL); r3_tree_insert_path(n, "/{id}", NULL); r3_tree_compile(n); r3_tree_compile(n); // test double compile #ifdef DEBUG r3_tree_dump(n, 0); #endif /* fail_if(n->edges[0]->child->combined_pattern == NULL); e = r3_node_find_edge_str(n, "/", strlen("/") ); fail_if( NULL == e ); */ /* printf( "%s\n", e->pattern ); printf( "%s\n", e->child->combined_pattern ); printf( "%s\n", n->edges[0]->child->combined_pattern); printf( "%s\n", n->combined_pattern ); */ match_entry * entry; entry = match_entry_createl( "foo" , strlen("/foo") ); m = r3_tree_matchl( n , "/foo", strlen("/foo"), entry); fail_if( NULL == m ); entry = match_entry_createl( "/zoo" , strlen("/zoo") ); m = r3_tree_matchl( n , "/zoo", strlen("/zoo"), entry); fail_if( NULL == m ); entry = match_entry_createl( "/bar" , strlen("/bar") ); m = r3_tree_matchl( n , "/bar", strlen("/bar"), entry); fail_if( NULL == m ); entry = match_entry_createl( "/xxx" , strlen("/xxx") ); m = r3_tree_matchl( n , "/xxx", strlen("/xxx"), entry); fail_if( NULL == m ); entry = match_entry_createl( "/foo/xxx" , strlen("/foo/xxx") ); m = r3_tree_matchl( n , "/foo/xxx", strlen("/foo/xxx"), entry); fail_if( NULL == m ); entry = match_entry_createl( "/some_id" , strlen("/some_id") ); m = r3_tree_matchl( n , "/some_id", strlen("/some_id"), entry); fail_if( NULL == m ); ck_assert_int_gt( m->endpoint , 0 ); // should not be an endpoint }
END_TEST START_TEST(benchmark_str) { match_entry * entry = match_entry_createl("/blog/post", strlen("/blog/post") ); node * n = r3_tree_create(1); int route_data = 999; r3_tree_insert_path(n, "/foo/bar/baz", NULL); r3_tree_insert_path(n, "/foo/bar/qux", NULL); r3_tree_insert_path(n, "/foo/bar/quux", NULL); r3_tree_insert_path(n, "/foo/bar/corge", NULL); r3_tree_insert_path(n, "/foo/bar/grault", NULL); r3_tree_insert_path(n, "/foo/bar/garply", NULL); r3_tree_insert_path(n, "/foo/baz/bar", NULL); r3_tree_insert_path(n, "/foo/baz/qux", NULL); r3_tree_insert_path(n, "/foo/baz/quux", NULL); r3_tree_insert_path(n, "/foo/baz/corge", NULL); r3_tree_insert_path(n, "/foo/baz/grault", NULL); r3_tree_insert_path(n, "/foo/baz/garply", NULL); r3_tree_insert_path(n, "/foo/qux/bar", NULL); r3_tree_insert_path(n, "/foo/qux/baz", NULL); r3_tree_insert_path(n, "/foo/qux/quux", NULL); r3_tree_insert_path(n, "/foo/qux/corge", NULL); r3_tree_insert_path(n, "/foo/qux/grault", NULL); r3_tree_insert_path(n, "/foo/qux/garply", NULL); r3_tree_insert_path(n, "/foo/quux/bar", NULL); r3_tree_insert_path(n, "/foo/quux/baz", NULL); r3_tree_insert_path(n, "/foo/quux/qux", NULL); r3_tree_insert_path(n, "/foo/quux/corge", NULL); r3_tree_insert_path(n, "/foo/quux/grault", NULL); r3_tree_insert_path(n, "/foo/quux/garply", NULL); r3_tree_insert_path(n, "/foo/corge/bar", NULL); r3_tree_insert_path(n, "/foo/corge/baz", NULL); r3_tree_insert_path(n, "/foo/corge/qux", NULL); r3_tree_insert_path(n, "/foo/corge/quux", NULL); r3_tree_insert_path(n, "/foo/corge/grault", NULL); r3_tree_insert_path(n, "/foo/corge/garply", NULL); r3_tree_insert_path(n, "/foo/grault/bar", NULL); r3_tree_insert_path(n, "/foo/grault/baz", NULL); r3_tree_insert_path(n, "/foo/grault/qux", NULL); r3_tree_insert_path(n, "/foo/grault/quux", NULL); r3_tree_insert_path(n, "/foo/grault/corge", NULL); r3_tree_insert_path(n, "/foo/grault/garply", NULL); r3_tree_insert_path(n, "/foo/garply/bar", NULL); r3_tree_insert_path(n, "/foo/garply/baz", NULL); r3_tree_insert_path(n, "/foo/garply/qux", NULL); r3_tree_insert_path(n, "/foo/garply/quux", NULL); r3_tree_insert_path(n, "/foo/garply/corge", NULL); r3_tree_insert_path(n, "/foo/garply/grault", NULL); r3_tree_insert_path(n, "/bar/foo/baz", NULL); r3_tree_insert_path(n, "/bar/foo/qux", NULL); r3_tree_insert_path(n, "/bar/foo/quux", NULL); r3_tree_insert_path(n, "/bar/foo/corge", NULL); r3_tree_insert_path(n, "/bar/foo/grault", NULL); r3_tree_insert_path(n, "/bar/foo/garply", NULL); r3_tree_insert_path(n, "/bar/baz/foo", NULL); r3_tree_insert_path(n, "/bar/baz/qux", NULL); r3_tree_insert_path(n, "/bar/baz/quux", NULL); r3_tree_insert_path(n, "/bar/baz/corge", NULL); r3_tree_insert_path(n, "/bar/baz/grault", NULL); r3_tree_insert_path(n, "/bar/baz/garply", NULL); r3_tree_insert_path(n, "/bar/qux/foo", NULL); r3_tree_insert_path(n, "/bar/qux/baz", NULL); r3_tree_insert_path(n, "/bar/qux/quux", NULL); r3_tree_insert_path(n, "/bar/qux/corge", NULL); r3_tree_insert_path(n, "/bar/qux/grault", NULL); r3_tree_insert_path(n, "/bar/qux/garply", NULL); r3_tree_insert_path(n, "/bar/quux/foo", NULL); r3_tree_insert_path(n, "/bar/quux/baz", NULL); r3_tree_insert_path(n, "/bar/quux/qux", NULL); r3_tree_insert_path(n, "/bar/quux/corge", NULL); r3_tree_insert_path(n, "/bar/quux/grault", NULL); r3_tree_insert_path(n, "/bar/quux/garply", NULL); r3_tree_insert_path(n, "/bar/corge/foo", NULL); r3_tree_insert_path(n, "/bar/corge/baz", NULL); r3_tree_insert_path(n, "/bar/corge/qux", NULL); r3_tree_insert_path(n, "/bar/corge/quux", NULL); r3_tree_insert_path(n, "/bar/corge/grault", NULL); r3_tree_insert_path(n, "/bar/corge/garply", NULL); r3_tree_insert_path(n, "/bar/grault/foo", NULL); r3_tree_insert_path(n, "/bar/grault/baz", NULL); r3_tree_insert_path(n, "/bar/grault/qux", NULL); r3_tree_insert_path(n, "/bar/grault/quux", NULL); r3_tree_insert_path(n, "/bar/grault/corge", NULL); r3_tree_insert_path(n, "/bar/grault/garply", NULL); r3_tree_insert_path(n, "/bar/garply/foo", NULL); r3_tree_insert_path(n, "/bar/garply/baz", NULL); r3_tree_insert_path(n, "/bar/garply/qux", NULL); r3_tree_insert_path(n, "/bar/garply/quux", NULL); r3_tree_insert_path(n, "/bar/garply/corge", NULL); r3_tree_insert_path(n, "/bar/garply/grault", NULL); r3_tree_insert_path(n, "/baz/foo/bar", NULL); r3_tree_insert_path(n, "/baz/foo/qux", NULL); r3_tree_insert_path(n, "/baz/foo/quux", NULL); r3_tree_insert_path(n, "/baz/foo/corge", NULL); r3_tree_insert_path(n, "/baz/foo/grault", NULL); r3_tree_insert_path(n, "/baz/foo/garply", NULL); r3_tree_insert_path(n, "/baz/bar/foo", NULL); r3_tree_insert_path(n, "/baz/bar/qux", NULL); r3_tree_insert_path(n, "/baz/bar/quux", NULL); r3_tree_insert_path(n, "/baz/bar/corge", NULL); r3_tree_insert_path(n, "/baz/bar/grault", NULL); r3_tree_insert_path(n, "/baz/bar/garply", NULL); r3_tree_insert_path(n, "/baz/qux/foo", NULL); r3_tree_insert_path(n, "/baz/qux/bar", NULL); r3_tree_insert_path(n, "/baz/qux/quux", NULL); r3_tree_insert_path(n, "/baz/qux/corge", NULL); r3_tree_insert_path(n, "/baz/qux/grault", NULL); r3_tree_insert_path(n, "/baz/qux/garply", NULL); r3_tree_insert_path(n, "/baz/quux/foo", NULL); r3_tree_insert_path(n, "/baz/quux/bar", NULL); r3_tree_insert_path(n, "/baz/quux/qux", NULL); r3_tree_insert_path(n, "/baz/quux/corge", NULL); r3_tree_insert_path(n, "/baz/quux/grault", NULL); r3_tree_insert_path(n, "/baz/quux/garply", NULL); r3_tree_insert_path(n, "/baz/corge/foo", NULL); r3_tree_insert_path(n, "/baz/corge/bar", NULL); r3_tree_insert_path(n, "/baz/corge/qux", NULL); r3_tree_insert_path(n, "/baz/corge/quux", NULL); r3_tree_insert_path(n, "/baz/corge/grault", NULL); r3_tree_insert_path(n, "/baz/corge/garply", NULL); r3_tree_insert_path(n, "/baz/grault/foo", NULL); r3_tree_insert_path(n, "/baz/grault/bar", NULL); r3_tree_insert_path(n, "/baz/grault/qux", NULL); r3_tree_insert_path(n, "/baz/grault/quux", NULL); r3_tree_insert_path(n, "/baz/grault/corge", NULL); r3_tree_insert_path(n, "/baz/grault/garply", NULL); r3_tree_insert_path(n, "/baz/garply/foo", NULL); r3_tree_insert_path(n, "/baz/garply/bar", NULL); r3_tree_insert_path(n, "/baz/garply/qux", NULL); r3_tree_insert_path(n, "/baz/garply/quux", NULL); r3_tree_insert_path(n, "/baz/garply/corge", NULL); r3_tree_insert_path(n, "/baz/garply/grault", NULL); r3_tree_insert_path(n, "/qux/foo/bar", NULL); r3_tree_insert_path(n, "/qux/foo/baz", NULL); r3_tree_insert_path(n, "/qux/foo/quux", NULL); r3_tree_insert_path(n, "/qux/foo/corge", NULL); r3_tree_insert_path(n, "/qux/foo/grault", NULL); r3_tree_insert_path(n, "/qux/foo/garply", NULL); r3_tree_insert_path(n, "/qux/bar/foo", NULL); r3_tree_insert_path(n, "/qux/bar/baz", NULL); r3_tree_insert_path(n, "/qux/bar/quux", NULL); r3_tree_insert_path(n, "/qux/bar/corge", &route_data); r3_tree_insert_path(n, "/qux/bar/grault", NULL); r3_tree_insert_path(n, "/qux/bar/garply", NULL); r3_tree_insert_path(n, "/qux/baz/foo", NULL); r3_tree_insert_path(n, "/qux/baz/bar", NULL); r3_tree_insert_path(n, "/qux/baz/quux", NULL); r3_tree_insert_path(n, "/qux/baz/corge", NULL); r3_tree_insert_path(n, "/qux/baz/grault", NULL); r3_tree_insert_path(n, "/qux/baz/garply", NULL); r3_tree_insert_path(n, "/qux/quux/foo", NULL); r3_tree_insert_path(n, "/qux/quux/bar", NULL); r3_tree_insert_path(n, "/qux/quux/baz", NULL); r3_tree_insert_path(n, "/qux/quux/corge", NULL); r3_tree_insert_path(n, "/qux/quux/grault", NULL); r3_tree_insert_path(n, "/qux/quux/garply", NULL); r3_tree_insert_path(n, "/qux/corge/foo", NULL); r3_tree_insert_path(n, "/qux/corge/bar", NULL); r3_tree_insert_path(n, "/qux/corge/baz", NULL); r3_tree_insert_path(n, "/qux/corge/quux", NULL); r3_tree_insert_path(n, "/qux/corge/grault", NULL); r3_tree_insert_path(n, "/qux/corge/garply", NULL); r3_tree_insert_path(n, "/qux/grault/foo", NULL); r3_tree_insert_path(n, "/qux/grault/bar", NULL); r3_tree_insert_path(n, "/qux/grault/baz", NULL); r3_tree_insert_path(n, "/qux/grault/quux", NULL); r3_tree_insert_path(n, "/qux/grault/corge", NULL); r3_tree_insert_path(n, "/qux/grault/garply", NULL); r3_tree_insert_path(n, "/qux/garply/foo", NULL); r3_tree_insert_path(n, "/qux/garply/bar", NULL); r3_tree_insert_path(n, "/qux/garply/baz", NULL); r3_tree_insert_path(n, "/qux/garply/quux", NULL); r3_tree_insert_path(n, "/qux/garply/corge", NULL); r3_tree_insert_path(n, "/qux/garply/grault", NULL); r3_tree_insert_path(n, "/quux/foo/bar", NULL); r3_tree_insert_path(n, "/quux/foo/baz", NULL); r3_tree_insert_path(n, "/quux/foo/qux", NULL); r3_tree_insert_path(n, "/quux/foo/corge", NULL); r3_tree_insert_path(n, "/quux/foo/grault", NULL); r3_tree_insert_path(n, "/quux/foo/garply", NULL); r3_tree_insert_path(n, "/quux/bar/foo", NULL); r3_tree_insert_path(n, "/quux/bar/baz", NULL); r3_tree_insert_path(n, "/quux/bar/qux", NULL); r3_tree_insert_path(n, "/quux/bar/corge", NULL); r3_tree_insert_path(n, "/quux/bar/grault", NULL); r3_tree_insert_path(n, "/quux/bar/garply", NULL); r3_tree_insert_path(n, "/quux/baz/foo", NULL); r3_tree_insert_path(n, "/quux/baz/bar", NULL); r3_tree_insert_path(n, "/quux/baz/qux", NULL); r3_tree_insert_path(n, "/quux/baz/corge", NULL); r3_tree_insert_path(n, "/quux/baz/grault", NULL); r3_tree_insert_path(n, "/quux/baz/garply", NULL); r3_tree_insert_path(n, "/quux/qux/foo", NULL); r3_tree_insert_path(n, "/quux/qux/bar", NULL); r3_tree_insert_path(n, "/quux/qux/baz", NULL); r3_tree_insert_path(n, "/quux/qux/corge", NULL); r3_tree_insert_path(n, "/quux/qux/grault", NULL); r3_tree_insert_path(n, "/quux/qux/garply", NULL); r3_tree_insert_path(n, "/quux/corge/foo", NULL); r3_tree_insert_path(n, "/quux/corge/bar", NULL); r3_tree_insert_path(n, "/quux/corge/baz", NULL); r3_tree_insert_path(n, "/quux/corge/qux", NULL); r3_tree_insert_path(n, "/quux/corge/grault", NULL); r3_tree_insert_path(n, "/quux/corge/garply", NULL); r3_tree_insert_path(n, "/quux/grault/foo", NULL); r3_tree_insert_path(n, "/quux/grault/bar", NULL); r3_tree_insert_path(n, "/quux/grault/baz", NULL); r3_tree_insert_path(n, "/quux/grault/qux", NULL); r3_tree_insert_path(n, "/quux/grault/corge", NULL); r3_tree_insert_path(n, "/quux/grault/garply", NULL); r3_tree_insert_path(n, "/quux/garply/foo", NULL); r3_tree_insert_path(n, "/quux/garply/bar", NULL); r3_tree_insert_path(n, "/quux/garply/baz", NULL); r3_tree_insert_path(n, "/quux/garply/qux", NULL); r3_tree_insert_path(n, "/quux/garply/corge", NULL); r3_tree_insert_path(n, "/quux/garply/grault", NULL); r3_tree_insert_path(n, "/corge/foo/bar", NULL); r3_tree_insert_path(n, "/corge/foo/baz", NULL); r3_tree_insert_path(n, "/corge/foo/qux", NULL); r3_tree_insert_path(n, "/corge/foo/quux", NULL); r3_tree_insert_path(n, "/corge/foo/grault", NULL); r3_tree_insert_path(n, "/corge/foo/garply", NULL); r3_tree_insert_path(n, "/corge/bar/foo", NULL); r3_tree_insert_path(n, "/corge/bar/baz", NULL); r3_tree_insert_path(n, "/corge/bar/qux", NULL); r3_tree_insert_path(n, "/corge/bar/quux", NULL); r3_tree_insert_path(n, "/corge/bar/grault", NULL); r3_tree_insert_path(n, "/corge/bar/garply", NULL); r3_tree_insert_path(n, "/corge/baz/foo", NULL); r3_tree_insert_path(n, "/corge/baz/bar", NULL); r3_tree_insert_path(n, "/corge/baz/qux", NULL); r3_tree_insert_path(n, "/corge/baz/quux", NULL); r3_tree_insert_path(n, "/corge/baz/grault", NULL); r3_tree_insert_path(n, "/corge/baz/garply", NULL); r3_tree_insert_path(n, "/corge/qux/foo", NULL); r3_tree_insert_path(n, "/corge/qux/bar", NULL); r3_tree_insert_path(n, "/corge/qux/baz", NULL); r3_tree_insert_path(n, "/corge/qux/quux", NULL); r3_tree_insert_path(n, "/corge/qux/grault", NULL); r3_tree_insert_path(n, "/corge/qux/garply", NULL); r3_tree_insert_path(n, "/corge/quux/foo", NULL); r3_tree_insert_path(n, "/corge/quux/bar", NULL); r3_tree_insert_path(n, "/corge/quux/baz", NULL); r3_tree_insert_path(n, "/corge/quux/qux", NULL); r3_tree_insert_path(n, "/corge/quux/grault", NULL); r3_tree_insert_path(n, "/corge/quux/garply", NULL); r3_tree_insert_path(n, "/corge/grault/foo", NULL); r3_tree_insert_path(n, "/corge/grault/bar", NULL); r3_tree_insert_path(n, "/corge/grault/baz", NULL); r3_tree_insert_path(n, "/corge/grault/qux", NULL); r3_tree_insert_path(n, "/corge/grault/quux", NULL); r3_tree_insert_path(n, "/corge/grault/garply", NULL); r3_tree_insert_path(n, "/corge/garply/foo", NULL); r3_tree_insert_path(n, "/corge/garply/bar", NULL); r3_tree_insert_path(n, "/corge/garply/baz", NULL); r3_tree_insert_path(n, "/corge/garply/qux", NULL); r3_tree_insert_path(n, "/corge/garply/quux", NULL); r3_tree_insert_path(n, "/corge/garply/grault", NULL); r3_tree_insert_path(n, "/grault/foo/bar", NULL); r3_tree_insert_path(n, "/grault/foo/baz", NULL); r3_tree_insert_path(n, "/grault/foo/qux", NULL); r3_tree_insert_path(n, "/grault/foo/quux", NULL); r3_tree_insert_path(n, "/grault/foo/corge", NULL); r3_tree_insert_path(n, "/grault/foo/garply", NULL); r3_tree_insert_path(n, "/grault/bar/foo", NULL); r3_tree_insert_path(n, "/grault/bar/baz", NULL); r3_tree_insert_path(n, "/grault/bar/qux", NULL); r3_tree_insert_path(n, "/grault/bar/quux", NULL); r3_tree_insert_path(n, "/grault/bar/corge", NULL); r3_tree_insert_path(n, "/grault/bar/garply", NULL); r3_tree_insert_path(n, "/grault/baz/foo", NULL); r3_tree_insert_path(n, "/grault/baz/bar", NULL); r3_tree_insert_path(n, "/grault/baz/qux", NULL); r3_tree_insert_path(n, "/grault/baz/quux", NULL); r3_tree_insert_path(n, "/grault/baz/corge", NULL); r3_tree_insert_path(n, "/grault/baz/garply", NULL); r3_tree_insert_path(n, "/grault/qux/foo", NULL); r3_tree_insert_path(n, "/grault/qux/bar", NULL); r3_tree_insert_path(n, "/grault/qux/baz", NULL); r3_tree_insert_path(n, "/grault/qux/quux", NULL); r3_tree_insert_path(n, "/grault/qux/corge", NULL); r3_tree_insert_path(n, "/grault/qux/garply", NULL); r3_tree_insert_path(n, "/grault/quux/foo", NULL); r3_tree_insert_path(n, "/grault/quux/bar", NULL); r3_tree_insert_path(n, "/grault/quux/baz", NULL); r3_tree_insert_path(n, "/grault/quux/qux", NULL); r3_tree_insert_path(n, "/grault/quux/corge", NULL); r3_tree_insert_path(n, "/grault/quux/garply", NULL); r3_tree_insert_path(n, "/grault/corge/foo", NULL); r3_tree_insert_path(n, "/grault/corge/bar", NULL); r3_tree_insert_path(n, "/grault/corge/baz", NULL); r3_tree_insert_path(n, "/grault/corge/qux", NULL); r3_tree_insert_path(n, "/grault/corge/quux", NULL); r3_tree_insert_path(n, "/grault/corge/garply", NULL); r3_tree_insert_path(n, "/grault/garply/foo", NULL); r3_tree_insert_path(n, "/grault/garply/bar", NULL); r3_tree_insert_path(n, "/grault/garply/baz", NULL); r3_tree_insert_path(n, "/grault/garply/qux", NULL); r3_tree_insert_path(n, "/grault/garply/quux", NULL); r3_tree_insert_path(n, "/grault/garply/corge", NULL); r3_tree_insert_path(n, "/garply/foo/bar", NULL); r3_tree_insert_path(n, "/garply/foo/baz", NULL); r3_tree_insert_path(n, "/garply/foo/qux", NULL); r3_tree_insert_path(n, "/garply/foo/quux", NULL); r3_tree_insert_path(n, "/garply/foo/corge", NULL); r3_tree_insert_path(n, "/garply/foo/grault", NULL); r3_tree_insert_path(n, "/garply/bar/foo", NULL); r3_tree_insert_path(n, "/garply/bar/baz", NULL); r3_tree_insert_path(n, "/garply/bar/qux", NULL); r3_tree_insert_path(n, "/garply/bar/quux", NULL); r3_tree_insert_path(n, "/garply/bar/corge", NULL); r3_tree_insert_path(n, "/garply/bar/grault", NULL); r3_tree_insert_path(n, "/garply/baz/foo", NULL); r3_tree_insert_path(n, "/garply/baz/bar", NULL); r3_tree_insert_path(n, "/garply/baz/qux", NULL); r3_tree_insert_path(n, "/garply/baz/quux", NULL); r3_tree_insert_path(n, "/garply/baz/corge", NULL); r3_tree_insert_path(n, "/garply/baz/grault", NULL); r3_tree_insert_path(n, "/garply/qux/foo", NULL); r3_tree_insert_path(n, "/garply/qux/bar", NULL); r3_tree_insert_path(n, "/garply/qux/baz", NULL); r3_tree_insert_path(n, "/garply/qux/quux", NULL); r3_tree_insert_path(n, "/garply/qux/corge", NULL); r3_tree_insert_path(n, "/garply/qux/grault", NULL); r3_tree_insert_path(n, "/garply/quux/foo", NULL); r3_tree_insert_path(n, "/garply/quux/bar", NULL); r3_tree_insert_path(n, "/garply/quux/baz", NULL); r3_tree_insert_path(n, "/garply/quux/qux", NULL); r3_tree_insert_path(n, "/garply/quux/corge", NULL); r3_tree_insert_path(n, "/garply/quux/grault", NULL); r3_tree_insert_path(n, "/garply/corge/foo", NULL); r3_tree_insert_path(n, "/garply/corge/bar", NULL); r3_tree_insert_path(n, "/garply/corge/baz", NULL); r3_tree_insert_path(n, "/garply/corge/qux", NULL); r3_tree_insert_path(n, "/garply/corge/quux", NULL); r3_tree_insert_path(n, "/garply/corge/grault", NULL); r3_tree_insert_path(n, "/garply/grault/foo", NULL); r3_tree_insert_path(n, "/garply/grault/bar", NULL); r3_tree_insert_path(n, "/garply/grault/baz", NULL); r3_tree_insert_path(n, "/garply/grault/qux", NULL); r3_tree_insert_path(n, "/garply/grault/quux", NULL); r3_tree_insert_path(n, "/garply/grault/corge", NULL); r3_tree_compile(n); // r3_tree_dump(n, 0); // match_entry *entry = calloc( sizeof(entry) , 1 ); node *m; m = r3_tree_match(n , "/qux/bar/corge", NULL); fail_if( m == NULL ); // r3_tree_dump( m, 0 ); ck_assert_int_eq( *((int*) m->data), 999 ); printf("Benchmarking...\n"); BENCHMARK(string_dispatch) r3_tree_matchl(n , "/qux/bar/corge", strlen("/qux/bar/corge"), NULL); END_BENCHMARK() bench_print_summary(&B); FILE *fp = fopen("bench_str.csv", "a+"); fprintf(fp, "%ld,%.2f\n", unixtime(), (B.N * B.R) / (B.end - B.start)); fclose(fp); }