remove route_split_pattern function
This commit is contained in:
parent
7687dd3aef
commit
e0eca85cbc
6 changed files with 140 additions and 167 deletions
23
include/r3.h
23
include/r3.h
|
@ -28,10 +28,14 @@ typedef struct _node node;
|
|||
typedef struct _route route;
|
||||
|
||||
struct _node {
|
||||
edge ** edges;
|
||||
edge ** edges;
|
||||
int edge_len;
|
||||
int edge_cap;
|
||||
|
||||
route ** conditions;
|
||||
int condition_len;
|
||||
int condition_cap;
|
||||
|
||||
|
||||
/** compile-time variables here.... **/
|
||||
|
||||
|
@ -56,7 +60,6 @@ struct _edge {
|
|||
int pattern_len;
|
||||
bool has_slug;
|
||||
node * child;
|
||||
route * route;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
@ -85,7 +88,6 @@ struct _route {
|
|||
|
||||
char * remote_addr_pattern;
|
||||
int remote_addr_pattern_len;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -97,11 +99,11 @@ void r3_tree_free(node * tree);
|
|||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
node * r3_tree_lookup(node * tree, char * path, int path_len);
|
||||
|
||||
edge * r3_edge_create(char * pattern, int pattern_len, node * child);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
node * r3_tree_insert_route(node *tree, route * route, void * data);
|
||||
|
||||
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);
|
||||
|
||||
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_POST 2<<1
|
||||
#define METHOD_PUT 2<<1
|
||||
#define METHOD_DELETE 2<<1
|
||||
|
||||
#endif /* !NODE_H */
|
||||
|
|
22
src/edge.c
22
src/edge.c
|
@ -24,6 +24,14 @@
|
|||
#include "r3.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.
|
||||
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->edge_len = 0;
|
||||
|
@ -55,20 +63,10 @@ void r3_edge_branch(edge *e, int dl) {
|
|||
|
||||
info("branched pattern: %s\n", e1->pattern);
|
||||
|
||||
r3_tree_append_edge(e->child, e1);
|
||||
r3_node_append_edge(e->child, e1);
|
||||
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) {
|
||||
if (e->pattern) {
|
||||
free(e->pattern);
|
||||
|
|
126
src/node.c
126
src/node.c
|
@ -63,7 +63,7 @@ void r3_tree_free(node * tree) {
|
|||
|
||||
|
||||
/* 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
|
||||
|
||||
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);
|
||||
r3_tree_append_edge(n, e);
|
||||
r3_node_append_edge(n, e);
|
||||
// str_array_append(n->edge_patterns, pat);
|
||||
// assert( str_array_len(n->edge_patterns) == n->edge_len );
|
||||
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) {
|
||||
n->edge_cap = 3;
|
||||
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 * 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 * n = (node*) malloc( sizeof(node) );
|
||||
n->edges = NULL;
|
||||
n->edge_len = 0;
|
||||
n->edge_cap = 0;
|
||||
|
||||
n->conditions = NULL;
|
||||
n->condition_len = 0;
|
||||
n->condition_cap = 0;
|
||||
|
||||
n->endpoint = 0;
|
||||
n->combined_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)
|
||||
{
|
||||
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 * n = tree;
|
||||
|
@ -405,19 +400,19 @@ node * r3_tree_insert_pathl(node *tree, char *path, int path_len, route * route,
|
|||
if ( offset == 0 ) {
|
||||
// not found, we should just insert a whole new edge
|
||||
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);
|
||||
child->data = data;
|
||||
child->endpoint++;
|
||||
return child;
|
||||
} else if ( offset == e->pattern_len ) { // fully-equal to the pattern of the edge
|
||||
|
||||
char * subroute = path + offset;
|
||||
int subroute_len = path_len - offset;
|
||||
char * subpath = path + offset;
|
||||
int subpath_len = path_len - offset;
|
||||
|
||||
// there are something more we can insert
|
||||
if ( subroute_len > 0 ) {
|
||||
return r3_tree_insert_pathl(e->child, subroute, subroute_len, route, data);
|
||||
if ( subpath_len > 0 ) {
|
||||
return r3_tree_insert_pathl(e->child, subpath, subpath_len, route, data);
|
||||
} else {
|
||||
// no more path to insert
|
||||
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;
|
||||
e2 = r3_edge_create(strndup(s2, s2_len), s2_len, c2);
|
||||
// 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;
|
||||
|
@ -551,6 +546,39 @@ int route_cmp(route *r1, route *r2) {
|
|||
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) {
|
||||
|
||||
|
|
52
src/token.c
52
src/token.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -102,3 +102,16 @@
|
|||
1400385528,13333901.32
|
||||
1400385535,11961732.08
|
||||
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
|
||||
|
|
|
|
@ -22,8 +22,8 @@ START_TEST (test_r3_node_construct_uniq)
|
|||
|
||||
node * child = r3_tree_create(3);
|
||||
|
||||
// fail_if( r3_tree_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 );
|
||||
// fail_if( r3_node_add_child(n, strdup("/add") , child) != NULL );
|
||||
|
||||
r3_tree_free(n);
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ START_TEST (test_r3_node_find_edge)
|
|||
|
||||
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, "/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)
|
||||
{
|
||||
|
@ -272,25 +237,38 @@ START_TEST(test_route_cmp)
|
|||
r2->request_method = METHOD_POST;
|
||||
fail_if( route_cmp(r1, r2) == 0, "should be different");
|
||||
|
||||
|
||||
route_free(r1);
|
||||
route_free(r2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
|
||||
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);
|
||||
|
||||
// route *info = route_create("/blog/post", strlen("/blog/post") );
|
||||
|
||||
// r3_tree_insert_route(n, "/foo/bar/baz", NULL);
|
||||
|
||||
match_entry_free(entry);
|
||||
route_free(r1);
|
||||
route_free(r2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
|
||||
START_TEST(benchmark_str)
|
||||
{
|
||||
match_entry * entry = match_entry_createl("/blog/post", strlen("/blog/post") );
|
||||
|
@ -667,7 +645,6 @@ Suite* r3_suite (void) {
|
|||
Suite *suite = suite_create("blah");
|
||||
|
||||
TCase *tcase = tcase_create("testcase");
|
||||
tcase_add_test(tcase, test_route_split);
|
||||
tcase_add_test(tcase, test_str_array);
|
||||
tcase_add_test(tcase, test_ltrim_slash);
|
||||
tcase_add_test(tcase, test_r3_node_construct_uniq);
|
||||
|
|
Loading…
Reference in a new issue