redge_branch function to branch the edge

This commit is contained in:
c9s 2014-05-15 23:46:49 +08:00
parent 9381ab943c
commit 824ae8784e
5 changed files with 118 additions and 56 deletions

View file

@ -49,6 +49,8 @@ rnode * rnode_lookup(rnode * tree, char * path, int path_len);
redge * redge_create(char * pattern, int pattern_len, rnode * child);
void redge_branch(redge *e, int dl);
void redge_free(redge * edge);
#endif /* !NODE_H */

View file

@ -12,7 +12,9 @@ int strndiff(char * d1, char * d2, unsigned int n);
int strdiff(char * d1, char * d2);
char * slug_to_pcre(char * slug, char sep);
char * compile_slug(char * str, int len);
char * contains_slug(char * str);
char * ltrim_slash(char* str);

View file

@ -236,12 +236,12 @@ rnode * rnode_insert_routel(rnode *tree, char *route, int route_len)
// branch the edge at correct position (avoid broken slugs)
char *slug_s = strchr(route, '{');
char *slug_e = strchr(route, '}');
if ( slug_s && slug_e ) {
if ( dl > (slug_s - route) && dl < (slug_e - route) ) {
// break before '{'
dl = slug_s - route;
}
}
/* it's partically matched with the pattern,
* we should split the end point and make a branch here...
@ -252,8 +252,44 @@ rnode * rnode_insert_routel(rnode *tree, char *route, int route_len)
char * s2 = route + dl;
int s1_len = 0, s2_len = 0;
redge_branch(e, dl);
// here is the new edge from.
c2 = rnode_create(3);
s2_len = route_len - dl;
e2 = redge_create(strndup(s2, s2_len), s2_len, c2);
// printf("edge right: %s\n", e2->pattern);
rnode_append_edge(e->child, e2);
// truncate the original edge pattern
free(e->pattern);
e->pattern = strndup(e->pattern, dl);
e->pattern_len = dl;
// move n->edges to c1
c2->endpoint++;
return c2;
} else if ( dl > 0 ) {
} else {
printf("unexpected condition.");
return NULL;
}
// token_array * t = split_route_pattern(route, strlen(route));
// return rnode_insert_tokens(tree, t);
// n->endpoint++;
return n;
}
void redge_branch(redge *e, int dl) {
rnode *c1; // child 1, child 2
redge *e1; // edge 1, edge 2
char * s1 = e->pattern + dl;
int s1_len = 0;
redge **tmp_edges = e->child->edges;
int **tmp_edge_len = e->child->edge_len;
int tmp_edge_len = e->child->edge_len;
// the suffix edge of the leaf
c1 = rnode_create(3);
@ -269,44 +305,7 @@ rnode * rnode_insert_routel(rnode *tree, char *route, int route_len)
e->child->edge_len = 0;
rnode_append_edge(e->child, e1);
// here is the new edge from.
c2 = rnode_create(3);
s2_len = route_len - dl;
e2 = redge_create(strndup(s2, s2_len), s2_len, c2);
// printf("edge right: %s\n", e2->pattern);
rnode_append_edge(e->child, e2);
// truncate the original edge pattern
free(e->pattern);
e->pattern = strndup(e->pattern, dl);
e->pattern_len = dl;
// Move the child edges to the new suffix edge child
/*
e->child->edge_len = 0;
*/
// move n->edges to c1
c1->endpoint++;
c2->endpoint++;
return c2;
} else if ( dl > 0 ) {
} else {
printf("unexpected condition.");
return NULL;
}
// token_array * t = split_route_pattern(route, strlen(route));
// return rnode_insert_tokens(tree, t);
// n->endpoint++;
return n;
}
void rnode_dump(rnode * n, int level) {

View file

@ -32,29 +32,71 @@ int strdiff(char * d1, char * d2) {
char * contains_slug(char * str) {
return strchr(str, '}');
}
/**
* @param char * sep separator
*/
char * slug_to_pcre(char * slug, char sep)
char * compile_slug(char * str, int len)
{
char * p = NULL;
char *s1 = NULL, *s2 = NULL, *i = NULL, *o = NULL;
char *pat = NULL;
char * end = NULL;
char sep = '/';
if ( NULL != (p = strchr(slug, ':')) ) {
// this slug contains a pattern
end = strchr(p, '}');
// find '{'
s1 = strchr(str, '{');
// start after ':'
return strndup( (p + 1) , (end - p - 1) );
} else {
if ((pat = malloc(128)) == NULL) {
if ( s1 == NULL ) {
return strdup(str);
}
if ( (s1 - str) > 0 ) {
sep = *(s1-1);
}
char * out = NULL;
if ((out = calloc(sizeof(char),128)) == NULL) {
return (NULL);
}
// append prefix
o = out;
strncat(o, str, s1 - str);
o += (s1 - str);
// start after ':'
if ( NULL != (pat = strchr(s1, ':')) ) {
pat++;
// this slug contains a pattern
s2 = strchr(pat, '}');
*o = '(';
o++;
strncat(o, pat, (s2 - pat) );
o += (s2 - pat);
*o = ')';
o++;
} else {
// should return a '[^/]+' pattern
snprintf(pat, 128, "[^%c]+", sep);
// strncat(c, "([^%c]+)", strlen("([^%c]+)") );
// snprintf(pat, 128, "([^%c]+)", sep);
sprintf(o, "([^%c]+)", sep);
o+= sizeof("([^%c]+)");
}
return pat;
s2++;
while( (s2 - str) > len ) {
*o = *s2;
s2++;
o++;
}
return out;
}

View file

@ -62,20 +62,37 @@ START_TEST (test_combine_patterns)
}
END_TEST
START_TEST (test_slug_to_pcre)
START_TEST (test_compile_slug)
{
/*
char * pattern;
pattern = slug_to_pcre("{id}", '/');
fail_if( strcmp(pattern, "[^/]+") != 0 , "as [^/]+" );
pattern = compile_slug("{id}", strlen("{id}"));
ck_assert_str_eq( pattern, "([^/]+)" );
free(pattern);
pattern = slug_to_pcre("{id:[a-z]+}", '/');
fail_if( strcmp(pattern, "[a-z]+") != 0 , "as [a-z]+" );
pattern = compile_slug("/{id}", strlen("/{id}"));
ck_assert_str_eq( pattern, "/([^/]+)" );
free(pattern);
pattern = compile_slug("-{id}", strlen("-{id}"));
ck_assert_str_eq( pattern, "-([^-]+)" );
free(pattern);
pattern = compile_slug("{id}-{title}", strlen("{id}-{title}"));
ck_assert_str_eq( pattern, "([^/]+)-([^-]+)" );
free(pattern);
pattern = compile_slug("{id:[a-z]+}", strlen("{id:[a-z]+}") );
ck_assert_str_eq( pattern, "([a-z]+)" );
free(pattern);
pattern = compile_slug("/path/{id:[a-z]+}", strlen("/path/{id:[a-z]+}") );
ck_assert_str_eq( pattern, "/path/([a-z]+)" );
free(pattern);
*/
/*
char * p = malloc(sizeof(char) * 10);
strncat(p, "foo", 3);
@ -221,7 +238,7 @@ Suite* r3_suite (void) {
tcase_add_test(tcase, test_rnode_construct_uniq);
tcase_add_test(tcase, test_rnode_find_edge);
tcase_add_test(tcase, test_rnode_insert_routel);
tcase_add_test(tcase, test_slug_to_pcre);
tcase_add_test(tcase, test_compile_slug);
tcase_add_test(tcase, test_combine_patterns);
suite_add_tcase(suite, tcase);