remove route_split_pattern function

This commit is contained in:
c9s 2014-05-18 12:24:07 +08:00
parent 7687dd3aef
commit e0eca85cbc
6 changed files with 140 additions and 167 deletions

View file

@ -28,10 +28,14 @@ typedef struct _node node;
typedef struct _route route; typedef struct _route route;
struct _node { struct _node {
edge ** edges; edge ** edges;
int edge_len; int edge_len;
int edge_cap; int edge_cap;
route ** conditions;
int condition_len;
int condition_cap;
/** compile-time variables here.... **/ /** compile-time variables here.... **/
@ -56,7 +60,6 @@ struct _edge {
int pattern_len; int pattern_len;
bool has_slug; bool has_slug;
node * child; node * child;
route * route;
}; };
typedef struct { typedef struct {
@ -85,7 +88,6 @@ struct _route {
char * remote_addr_pattern; char * remote_addr_pattern;
int remote_addr_pattern_len; int remote_addr_pattern_len;
}; };
@ -97,11 +99,11 @@ void r3_tree_free(node * tree);
void r3_edge_free(edge * edge); void r3_edge_free(edge * edge);
edge * r3_tree_add_child(node * n, char * pat , node *child); edge * r3_node_add_child(node * n, char * pat , node *child);
edge * r3_node_find_edge(node * n, char * pat); edge * r3_node_find_edge(node * n, char * pat);
void r3_tree_append_edge(node *n, edge *child); void r3_node_append_edge(node *n, edge *child);
node * r3_tree_insert_path(node *tree, char *path, route * route, void * data); node * r3_tree_insert_path(node *tree, char *path, route * route, void * data);
@ -124,8 +126,6 @@ node * r3_tree_match(node * n, char * path, int path_len, match_entry * entry);
bool r3_node_has_slug_edges(node *n); bool r3_node_has_slug_edges(node *n);
node * r3_tree_lookup(node * tree, char * path, int path_len);
edge * r3_edge_create(char * pattern, int pattern_len, node * child); edge * r3_edge_create(char * pattern, int pattern_len, node * child);
void r3_edge_branch(edge *e, int dl); void r3_edge_branch(edge *e, int dl);
@ -133,6 +133,7 @@ void r3_edge_branch(edge *e, int dl);
void r3_edge_free(edge * edge); void r3_edge_free(edge * edge);
node * r3_tree_insert_route(node *tree, route * route, void * data);
match_entry * match_entry_createl(char * path, int path_len); match_entry * match_entry_createl(char * path, int path_len);
@ -147,7 +148,15 @@ route * route_createl(char * path, int path_len);
int route_cmp(route *r1, route *r2); int route_cmp(route *r1, route *r2);
edge * r3_edge_route_create(route * route, node * child);
node * r3_node_append_condition(node * n, route * route, void * data);
void route_free(route * route);
#define METHOD_GET 2 #define METHOD_GET 2
#define METHOD_POST 2<<1 #define METHOD_POST 2<<1
#define METHOD_PUT 2<<1
#define METHOD_DELETE 2<<1
#endif /* !NODE_H */ #endif /* !NODE_H */

View file

@ -24,6 +24,14 @@
#include "r3.h" #include "r3.h"
#include "str_array.h" #include "str_array.h"
edge * r3_edge_create(char * pattern, int pattern_len, node * child) {
edge * e = (edge*) malloc( sizeof(edge) );
e->pattern = pattern;
e->pattern_len = pattern_len;
e->child = child;
return e;
}
/** /**
@ -47,7 +55,7 @@ void r3_edge_branch(edge *e, int dl) {
// Migrate the child edges to the new edge we just created. // Migrate the child edges to the new edge we just created.
for ( int i = 0 ; i < tmp_r3_edge_len ; i++ ) { for ( int i = 0 ; i < tmp_r3_edge_len ; i++ ) {
r3_tree_append_edge(c1, tmp_edges[i]); r3_node_append_edge(c1, tmp_edges[i]);
e->child->edges[i] = NULL; e->child->edges[i] = NULL;
} }
e->child->edge_len = 0; e->child->edge_len = 0;
@ -55,20 +63,10 @@ void r3_edge_branch(edge *e, int dl) {
info("branched pattern: %s\n", e1->pattern); info("branched pattern: %s\n", e1->pattern);
r3_tree_append_edge(e->child, e1); r3_node_append_edge(e->child, e1);
c1->endpoint++; c1->endpoint++;
} }
edge * r3_edge_create(char * pattern, int pattern_len, node * child) {
edge * e = (edge*) malloc( sizeof(edge) );
e->pattern = pattern;
e->pattern_len = pattern_len;
e->child = child;
e->route = NULL;
return e;
}
void r3_edge_free(edge * e) { void r3_edge_free(edge * e) {
if (e->pattern) { if (e->pattern) {
free(e->pattern); free(e->pattern);

View file

@ -63,7 +63,7 @@ void r3_tree_free(node * tree) {
/* parent node, edge pattern, child */ /* parent node, edge pattern, child */
edge * r3_tree_add_child(node * n, char * pat , node *child) { edge * r3_node_add_child(node * n, char * pat , node *child) {
// find the same sub-pattern, if it does not exist, create one // find the same sub-pattern, if it does not exist, create one
edge * e; edge * e;
@ -74,7 +74,7 @@ edge * r3_tree_add_child(node * n, char * pat , node *child) {
} }
e = r3_edge_create( pat, strlen(pat), child); e = r3_edge_create( pat, strlen(pat), child);
r3_tree_append_edge(n, e); r3_node_append_edge(n, e);
// str_array_append(n->edge_patterns, pat); // str_array_append(n->edge_patterns, pat);
// assert( str_array_len(n->edge_patterns) == n->edge_len ); // assert( str_array_len(n->edge_patterns) == n->edge_len );
return e; return e;
@ -82,8 +82,7 @@ edge * r3_tree_add_child(node * n, char * pat , node *child) {
void r3_tree_append_edge(node *n, edge *e) { void r3_node_append_edge(node *n, edge *e) {
if (!n->edges) { if (!n->edges) {
n->edge_cap = 3; n->edge_cap = 3;
n->edges = malloc(sizeof(edge) * n->edge_cap); n->edges = malloc(sizeof(edge) * n->edge_cap);
@ -194,27 +193,6 @@ void r3_tree_compile_patterns(node * n) {
} }
} }
route * route_create(char * path) {
return route_createl(path, strlen(path));
}
void route_free(route * route) {
free(route);
}
route * route_createl(char * path, int path_len) {
route * info = malloc(sizeof(route));
info->path = path;
info->path_len = path_len;
info->request_method = 0; // can be (GET || POST)
info->host = NULL; // required host name
info->host_len = 0;
info->remote_addr_pattern = NULL;
info->remote_addr_pattern_len = 0;
return info;
}
match_entry * match_entry_createl(char * path, int path_len) { match_entry * match_entry_createl(char * path, int path_len) {
match_entry * entry = malloc(sizeof(match_entry)); match_entry * entry = malloc(sizeof(match_entry));
@ -337,30 +315,17 @@ inline edge * r3_node_find_edge_str(node * n, char * str, int str_len) {
} }
node * r3_tree_lookup(node * tree, char * path, int path_len) {
str_array * tokens = split_route_pattern(path, path_len);
node * n = tree;
edge * e = NULL;
int i = 0;
for (; i < tokens->len ; i++ ) {
e = r3_node_find_edge(n, str_array_fetch(tokens, i) );
if (!e) {
return NULL;
}
n = e->child;
}
if (n->endpoint) {
return n;
}
return NULL;
}
node * r3_node_create() { node * r3_node_create() {
node * n = (node*) malloc( sizeof(node) ); node * n = (node*) malloc( sizeof(node) );
n->edges = NULL; n->edges = NULL;
n->edge_len = 0; n->edge_len = 0;
n->edge_cap = 0; n->edge_cap = 0;
n->conditions = NULL;
n->condition_len = 0;
n->condition_cap = 0;
n->endpoint = 0; n->endpoint = 0;
n->combined_pattern = NULL; n->combined_pattern = NULL;
n->pcre_pattern = NULL; n->pcre_pattern = NULL;
@ -368,11 +333,41 @@ node * r3_node_create() {
} }
route * route_create(char * path) {
return route_createl(path, strlen(path));
}
void route_free(route * route) {
free(route);
}
route * route_createl(char * path, int path_len) {
route * info = malloc(sizeof(route));
info->path = path;
info->path_len = path_len;
info->request_method = 0; // can be (GET || POST)
info->host = NULL; // required host name
info->host_len = 0;
info->remote_addr_pattern = NULL;
info->remote_addr_pattern_len = 0;
return info;
}
node * r3_tree_insert_route(node *tree, route * route, void * data) {
return r3_tree_insert_pathl(tree, route->path, route->path_len, route, data);
}
node * r3_tree_insert_path(node *tree, char *path, route * route, void * data) node * r3_tree_insert_path(node *tree, char *path, route * route, void * data)
{ {
return r3_tree_insert_pathl(tree, path, strlen(path) , route , data); return r3_tree_insert_pathl(tree, path, strlen(path) , route , data);
} }
/**
* Return the last inserted node.
*/
node * r3_tree_insert_pathl(node *tree, char *path, int path_len, route * route, void * data) node * r3_tree_insert_pathl(node *tree, char *path, int path_len, route * route, void * data)
{ {
node * n = tree; node * n = tree;
@ -405,19 +400,19 @@ node * r3_tree_insert_pathl(node *tree, char *path, int path_len, route * route,
if ( offset == 0 ) { if ( offset == 0 ) {
// not found, we should just insert a whole new edge // not found, we should just insert a whole new edge
node * child = r3_tree_create(3); node * child = r3_tree_create(3);
r3_tree_add_child(n, strndup(path, path_len) , child); r3_node_add_child(n, strndup(path, path_len) , child);
info("edge not found, insert one: %s\n", path); info("edge not found, insert one: %s\n", path);
child->data = data; child->data = data;
child->endpoint++; child->endpoint++;
return child; return child;
} else if ( offset == e->pattern_len ) { // fully-equal to the pattern of the edge } else if ( offset == e->pattern_len ) { // fully-equal to the pattern of the edge
char * subroute = path + offset; char * subpath = path + offset;
int subroute_len = path_len - offset; int subpath_len = path_len - offset;
// there are something more we can insert // there are something more we can insert
if ( subroute_len > 0 ) { if ( subpath_len > 0 ) {
return r3_tree_insert_pathl(e->child, subroute, subroute_len, route, data); return r3_tree_insert_pathl(e->child, subpath, subpath_len, route, data);
} else { } else {
// no more path to insert // no more path to insert
e->child->endpoint++; // make it as an endpoint e->child->endpoint++; // make it as an endpoint
@ -444,7 +439,7 @@ node * r3_tree_insert_pathl(node *tree, char *path, int path_len, route * route,
s2_len = path_len - offset; s2_len = path_len - offset;
e2 = r3_edge_create(strndup(s2, s2_len), s2_len, c2); e2 = r3_edge_create(strndup(s2, s2_len), s2_len, c2);
// printf("edge right: %s\n", e2->pattern); // printf("edge right: %s\n", e2->pattern);
r3_tree_append_edge(e->child, e2); r3_node_append_edge(e->child, e2);
char *op = e->pattern; char *op = e->pattern;
@ -551,6 +546,39 @@ int route_cmp(route *r1, route *r2) {
return 0; return 0;
} }
/**
* Create a data only node.
*/
node * r3_node_append_condition(node * n, route * route, void * data) {
/*
if (!n->conditions) {
n->condition_cap = 3;
n->conditions = malloc(sizeof(condition) * n->condition_cap);
}
if (n->condition_len >= n->condition_cap) {
n->condition_cap *= 2;
n->conditions = realloc(n->conditions, sizeof(condition) * n->condition_cap);
}
n->conditions[ n->condition_len++ ] = condition;
*/
return n;
}
/**
* Create a route-only edge. (without pattern)
*/
edge * r3_edge_route_create(route * route, node * child) {
edge * e = (edge*) malloc( sizeof(edge) );
/*
e->pattern = NULL;
e->pattern_len = 0;
e->child = child;
// e->route = NULL;
*/
return e;
}
/* /*
char * r3_node_trace(node * n) { char * r3_node_trace(node * n) {

View file

@ -63,55 +63,3 @@ void str_array_dump(str_array *l) {
/**
* This function is used to split route path into a string array, not for performance.
* hence this function should be safe.
*
* Split "/path/foo/{id}" into [ "/path" , "/foo" , "/{id}" ]
* Split "/path/bar/{id}" into [ "/path" , "/foo" , "/{id}" ]
* Split "/blog/post/{id}" into [ "/blog" , "/post" , "/{id}" ]
* Split "/blog/{id}" into [ "/blog" , "/{id}" ]
* Split "/blog" into [ "/blog" ]
* Split "/b" into [ "/b" ]
* Split "/{id}" into [ "/{id}" ]
*
* @param char* pattern
* @param int pattern_len
*
* @return char**
*/
str_array * split_route_pattern(char *pattern, int pattern_len) {
char *s1, *p = pattern;
str_array * str_array = str_array_create( 20 );
s1 = p;
p++;
while (*p && (p - pattern) < pattern_len ) {
// a slug
if ( *p == '{' ) {
// find closing '}'
while (*p != '}') {
p++;
assert(p - pattern < pattern_len ); // throw exception
}
p++; // contains the '}'
// printf("==> %s\n", strndup(s1, p-s1) );
str_array_append(str_array, strndup(s1, p-s1) );
s1 = p;
continue;
}
else if ( *p == '/' ) {
// printf("==> %s\n", strndup(s1, p-s1) );
str_array_append(str_array, strndup(s1, p-s1) );
s1 = p;
}
p++;
}
if ( p-s1 > 0 ) {
str_array_append(str_array, strndup(s1, p-s1) );
}
return str_array;
}

View file

@ -102,3 +102,16 @@
1400385528,13333901.32 1400385528,13333901.32
1400385535,11961732.08 1400385535,11961732.08
1400385563,12910309.71 1400385563,12910309.71
1400385616,12105227.61
1400385713,13601851.15
1400385728,13344674.03
1400385734,13685060.22
1400385774,13223631.32
1400385951,11001406.94
1400386286,10682057.04
1400386296,11152665.22
1400386480,10908179.24
1400386496,11514008.98
1400386505,11172976.25
1400386731,11184613.82
1400387044,10760384.75

1 1400242718 5649455.80
102 1400385528 13333901.32
103 1400385535 11961732.08
104 1400385563 12910309.71
105 1400385616 12105227.61
106 1400385713 13601851.15
107 1400385728 13344674.03
108 1400385734 13685060.22
109 1400385774 13223631.32
110 1400385951 11001406.94
111 1400386286 10682057.04
112 1400386296 11152665.22
113 1400386480 10908179.24
114 1400386496 11514008.98
115 1400386505 11172976.25
116 1400386731 11184613.82
117 1400387044 10760384.75

View file

@ -22,8 +22,8 @@ START_TEST (test_r3_node_construct_uniq)
node * child = r3_tree_create(3); node * child = r3_tree_create(3);
// fail_if( r3_tree_add_child(n, strdup("/add") , child) != NULL ); // fail_if( r3_node_add_child(n, strdup("/add") , child) != NULL );
// fail_if( r3_tree_add_child(n, strdup("/add") , child) != NULL ); // fail_if( r3_node_add_child(n, strdup("/add") , child) != NULL );
r3_tree_free(n); r3_tree_free(n);
} }
@ -35,7 +35,7 @@ START_TEST (test_r3_node_find_edge)
node * child = r3_tree_create(3); node * child = r3_tree_create(3);
fail_if( r3_tree_add_child(n, strdup("/add") , child) == FALSE ); fail_if( r3_node_add_child(n, strdup("/add") , child) == FALSE );
fail_if( r3_node_find_edge(n, "/add") == NULL ); fail_if( r3_node_find_edge(n, "/add") == NULL );
fail_if( r3_node_find_edge(n, "/bar") != NULL ); fail_if( r3_node_find_edge(n, "/bar") != NULL );
@ -198,41 +198,6 @@ END_TEST
START_TEST (test_route_split)
{
str_array *t;
t = split_route_pattern("/blog", strlen("/blog") );
fail_if( t == NULL );
// str_array_dump(t);
str_array_free(t);
t = split_route_pattern("/foo/{id}", strlen("/foo/{id}") );
fail_if( t == NULL );
// str_array_dump(t);
fail_if( t->len != 2 );
str_array_free(t);
t = split_route_pattern("/foo/bar/{id}", strlen("/foo/bar/{id}") );
fail_if( t == NULL );
// str_array_dump(t);
fail_if( t->len != 3 );
str_array_free(t);
t = split_route_pattern("/{title}", strlen("/{title}") );
fail_if( t == NULL );
// str_array_dump(t);
fail_if( t->len != 1 );
str_array_free(t);
t = split_route_pattern("/", strlen("/") );
fail_if( t == NULL );
// str_array_dump(t);
fail_if( t->len != 1 );
str_array_free(t);
}
END_TEST
START_TEST (test_str_array) START_TEST (test_str_array)
{ {
@ -272,25 +237,38 @@ START_TEST(test_route_cmp)
r2->request_method = METHOD_POST; r2->request_method = METHOD_POST;
fail_if( route_cmp(r1, r2) == 0, "should be different"); fail_if( route_cmp(r1, r2) == 0, "should be different");
route_free(r1);
route_free(r2);
} }
END_TEST END_TEST
START_TEST(test_insert_route) START_TEST(test_insert_route)
{ {
match_entry * entry = match_entry_createl("/blog/post", strlen("/blog/post") ); int var1 = 22;
int var2 = 33;
route *r1 = route_create("/blog/post");
route *r2 = route_create("/blog/post");
r1->request_method = METHOD_GET;
r2->request_method = METHOD_POST;
fail_if( route_cmp(r1, r2) == 0, "should be different");
match_entry * entry2 = match_entry_create("/blog/post"); match_entry * entry = match_entry_create("/blog/post");
node * n = r3_tree_create(2);
r3_tree_insert_route(n, r1, &var1);
r3_tree_insert_route(n, r2, &var2);
node * tree = r3_tree_create(2); match_entry_free(entry);
route_free(r1);
// route *info = route_create("/blog/post", strlen("/blog/post") ); route_free(r2);
// r3_tree_insert_route(n, "/foo/bar/baz", NULL);
} }
END_TEST END_TEST
START_TEST(benchmark_str) START_TEST(benchmark_str)
{ {
match_entry * entry = match_entry_createl("/blog/post", strlen("/blog/post") ); match_entry * entry = match_entry_createl("/blog/post", strlen("/blog/post") );
@ -667,7 +645,6 @@ Suite* r3_suite (void) {
Suite *suite = suite_create("blah"); Suite *suite = suite_create("blah");
TCase *tcase = tcase_create("testcase"); TCase *tcase = tcase_create("testcase");
tcase_add_test(tcase, test_route_split);
tcase_add_test(tcase, test_str_array); tcase_add_test(tcase, test_str_array);
tcase_add_test(tcase, test_ltrim_slash); tcase_add_test(tcase, test_ltrim_slash);
tcase_add_test(tcase, test_r3_node_construct_uniq); tcase_add_test(tcase, test_r3_node_construct_uniq);