error code support

- return error code if compilation error occurs
- use asprintf to sprint errstr
This commit is contained in:
c9s 2014-06-01 01:51:42 +08:00
parent 642fdfca88
commit 1a4eb14a05
5 changed files with 47 additions and 31 deletions

View file

@ -122,9 +122,9 @@ int r3_tree_render_dot(node * tree);
edge * r3_node_find_edge_str(const node * n, const char * str, int str_len); edge * r3_node_find_edge_str(const node * n, const char * str, int str_len);
void r3_tree_compile(node *n); int r3_tree_compile(node *n, char** errstr);
void r3_tree_compile_patterns(node * n); int r3_tree_compile_patterns(node * n, char** errstr);
node * r3_tree_matchl(const node * n, const char * path, int path_len, const match_entry * entry); node * r3_tree_matchl(const node * n, const char * path, int path_len, const match_entry * entry);

View file

@ -124,33 +124,41 @@ edge * r3_node_find_edge(const node * n, const char * pat) {
return NULL; return NULL;
} }
void r3_tree_compile(node *n) int r3_tree_compile(node *n, char **errstr)
{ {
int ret = 0;
bool use_slug = r3_node_has_slug_edges(n); bool use_slug = r3_node_has_slug_edges(n);
if ( use_slug ) { if ( use_slug ) {
r3_tree_compile_patterns(n); if ( (ret = r3_tree_compile_patterns(n, errstr)) ) {
return ret;
}
} else { } else {
// use normal text matching... // use normal text matching...
n->combined_pattern = NULL; n->combined_pattern = NULL;
} }
for (int i = 0 ; i < n->edge_len ; i++ ) { for (int i = 0 ; i < n->edge_len ; i++ ) {
r3_tree_compile(n->edges[i]->child); if ( (ret = r3_tree_compile(n->edges[i]->child, errstr)) ) {
return ret; // stop here if error occurs
} }
} }
return 0;
}
/** /**
* This function combines ['/foo', '/bar', '/{slug}'] into (/foo)|(/bar)|/([^/]+)} * This function combines ['/foo', '/bar', '/{slug}'] into (/foo)|(/bar)|/([^/]+)}
* *
*/ */
void r3_tree_compile_patterns(node * n) { int r3_tree_compile_patterns(node * n, char **errstr) {
char * cpat; char * cpat;
char * p; char * p;
cpat = zcalloc(sizeof(char) * 128); cpat = zcalloc(sizeof(char) * 220); // XXX
if (cpat==NULL) if (!cpat) {
return; asprintf(errstr, "Can not allocate memory");
return -1;
}
p = cpat; p = cpat;
@ -195,8 +203,8 @@ void r3_tree_compile_patterns(node * n) {
n->combined_pattern = cpat; n->combined_pattern = cpat;
const char *error; const char *pcre_error;
int erroffset; int pcre_erroffset;
unsigned int option_bits = 0; unsigned int option_bits = 0;
n->ov_cnt = (1 + n->edge_len) * 3; n->ov_cnt = (1 + n->edge_len) * 3;
@ -207,23 +215,28 @@ void r3_tree_compile_patterns(node * n) {
n->pcre_pattern = pcre_compile( n->pcre_pattern = pcre_compile(
n->combined_pattern, /* the pattern */ n->combined_pattern, /* the pattern */
option_bits, /* default options */ option_bits, /* default options */
&error, /* for error message */ &pcre_error, /* for error message */
&erroffset, /* for error offset */ &pcre_erroffset, /* for error offset */
NULL); /* use default character tables */ NULL); /* use default character tables */
if (n->pcre_pattern == NULL) { if (n->pcre_pattern == NULL) {
printf("PCRE compilation failed at offset %d: %s, pattern: %s\n", erroffset, error, n->combined_pattern); if (errstr) {
return; asprintf(errstr, "PCRE compilation failed at offset %d: %s, pattern: %s\n", pcre_erroffset, pcre_error, n->combined_pattern);
}
return -1;
} }
#ifdef PCRE_STUDY_JIT_COMPILE #ifdef PCRE_STUDY_JIT_COMPILE
if (n->pcre_extra) { if (n->pcre_extra) {
pcre_free_study(n->pcre_extra); pcre_free_study(n->pcre_extra);
} }
n->pcre_extra = pcre_study(n->pcre_pattern, 0, &error); n->pcre_extra = pcre_study(n->pcre_pattern, 0, &pcre_error);
if (n->pcre_extra == NULL) { if (n->pcre_extra == NULL) {
printf("PCRE study failed at offset %s\n", error); if (errstr) {
return; asprintf(errstr, "PCRE study failed at offset %s\n", pcre_error);
}
return -1;
} }
#endif #endif
return 0;
} }

View file

@ -441,7 +441,7 @@ r3_tree_insert_path(n, "/garply/grault/quux", NULL);
r3_tree_insert_path(n, "/garply/grault/corge", NULL); r3_tree_insert_path(n, "/garply/grault/corge", NULL);
MEASURE(tree_compile) MEASURE(tree_compile)
r3_tree_compile(n); r3_tree_compile(n, NULL);
END_MEASURE(tree_compile) END_MEASURE(tree_compile)
node *m; node *m;
@ -466,7 +466,7 @@ r3_tree_insert_path(n, "/garply/grault/corge", NULL);
node * tree2 = r3_tree_create(1); node * tree2 = r3_tree_create(1);
r3_tree_insert_path(tree2, "/post/{year}/{month}", NULL); r3_tree_insert_path(tree2, "/post/{year}/{month}", NULL);
r3_tree_compile(tree2); r3_tree_compile(tree2, NULL);
BENCHMARK(pcre_dispatch) BENCHMARK(pcre_dispatch)
r3_tree_matchl(tree2, "/post/2014/12", strlen("/post/2014/12"), NULL); r3_tree_matchl(tree2, "/post/2014/12", strlen("/post/2014/12"), NULL);

View file

@ -25,7 +25,7 @@ START_TEST (test_gvc_render_dot)
r3_tree_insert_path(n, "/garply/grault/foo", 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/bar", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
r3_tree_render_dot(n); r3_tree_render_dot(n);
@ -48,7 +48,7 @@ START_TEST (test_gvc_render_file)
r3_tree_insert_path(n, "/user/{id}", NULL); r3_tree_insert_path(n, "/user/{id}", NULL);
r3_tree_insert_path(n, "/post/{title:\\w+}", NULL); r3_tree_insert_path(n, "/post/{title:\\w+}", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
r3_tree_render_file(n, "png", "check_gvc.png"); r3_tree_render_file(n, "png", "check_gvc.png");
r3_tree_free(n); r3_tree_free(n);
} }

View file

@ -47,7 +47,7 @@ static node * create_simple_str_tree() {
r3_tree_insert_path(n, "/zoo", NULL); r3_tree_insert_path(n, "/zoo", NULL);
r3_tree_insert_path(n, "/foo", NULL); r3_tree_insert_path(n, "/foo", NULL);
r3_tree_insert_path(n, "/bar", NULL); r3_tree_insert_path(n, "/bar", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
return n; return n;
} }
@ -67,8 +67,8 @@ START_TEST (test_compile)
r3_tree_insert_path(n, "/foo/{id}", NULL); r3_tree_insert_path(n, "/foo/{id}", NULL);
r3_tree_insert_path(n, "/{id}", NULL); r3_tree_insert_path(n, "/{id}", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
r3_tree_compile(n); // test double compile r3_tree_compile(n, NULL); // test double compile
r3_tree_dump(n, 0); r3_tree_dump(n, 0);
match_entry * entry; match_entry * entry;
@ -104,7 +104,10 @@ START_TEST (test_pcre_patterns_insert)
// r3_tree_insert_path(n, "/foo-{user}-{id}", NULL, NULL); // 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/{handle:\\d+}-{id:\\d+}", NULL);
r3_tree_compile(n);
char *errstr = NULL;
r3_tree_compile(n, &errstr);
// r3_tree_dump(n, 0); // r3_tree_dump(n, 0);
node *matched; node *matched;
@ -131,7 +134,7 @@ START_TEST (test_pcre_patterns_insert_2)
r3_tree_insert_path(n, "/zoo", NULL); r3_tree_insert_path(n, "/zoo", NULL);
r3_tree_insert_path(n, "/foo", NULL); r3_tree_insert_path(n, "/foo", NULL);
r3_tree_insert_path(n, "/bar", NULL); r3_tree_insert_path(n, "/bar", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
r3_tree_dump(n, 0); r3_tree_dump(n, 0);
node *matched; node *matched;
matched = r3_tree_match(n, "/post/11/22", NULL); matched = r3_tree_match(n, "/post/11/22", NULL);
@ -156,7 +159,7 @@ START_TEST (test_pcre_patterns_insert_3)
r3_tree_insert_path(n, "/foo", NULL); r3_tree_insert_path(n, "/foo", NULL);
r3_tree_insert_path(n, "/bar", NULL); r3_tree_insert_path(n, "/bar", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
r3_tree_dump(n, 0); r3_tree_dump(n, 0);
node *matched; node *matched;
@ -202,7 +205,7 @@ START_TEST (testr3_tree_insert_pathl)
r3_tree_insert_path(n, "/post/{handle}", NULL); r3_tree_insert_path(n, "/post/{handle}", NULL);
r3_tree_insert_path(n, "/post/{handle}-{id}", NULL); r3_tree_insert_path(n, "/post/{handle}-{id}", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
#ifdef DEBUG #ifdef DEBUG
r3_tree_dump(n, 0); r3_tree_dump(n, 0);
@ -270,7 +273,7 @@ START_TEST(test_pcre_pattern_simple)
node * n = r3_tree_create(10); node * n = r3_tree_create(10);
r3_tree_insert_path(n, "/user/{id:\\d+}", NULL); r3_tree_insert_path(n, "/user/{id:\\d+}", NULL);
r3_tree_insert_path(n, "/user", NULL); r3_tree_insert_path(n, "/user", NULL);
r3_tree_compile(n); r3_tree_compile(n, NULL);
// r3_tree_dump(n, 0); // r3_tree_dump(n, 0);
node *matched; node *matched;
matched = r3_tree_matchl(n, "/user/123", strlen("/user/123"), entry); matched = r3_tree_matchl(n, "/user/123", strlen("/user/123"), entry);
@ -302,7 +305,7 @@ START_TEST(test_pcre_pattern_more)
r3_tree_insert_path(n, "/user2/{id:\\d+}", &var2); r3_tree_insert_path(n, "/user2/{id:\\d+}", &var2);
r3_tree_insert_path(n, "/user3/{id:\\d{3}}", &var3); r3_tree_insert_path(n, "/user3/{id:\\d{3}}", &var3);
r3_tree_insert_path(n, "/user", &var0); r3_tree_insert_path(n, "/user", &var0);
r3_tree_compile(n); r3_tree_compile(n, NULL);
r3_tree_dump(n, 0); r3_tree_dump(n, 0);
node *matched; node *matched;