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);
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);

View file

@ -124,33 +124,41 @@ edge * r3_node_find_edge(const node * n, const char * pat) {
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);
if ( use_slug ) {
r3_tree_compile_patterns(n);
if ( (ret = r3_tree_compile_patterns(n, errstr)) ) {
return ret;
}
} else {
// use normal text matching...
n->combined_pattern = NULL;
}
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)|/([^/]+)}
*
*/
void r3_tree_compile_patterns(node * n) {
int r3_tree_compile_patterns(node * n, char **errstr) {
char * cpat;
char * p;
cpat = zcalloc(sizeof(char) * 128);
if (cpat==NULL)
return;
cpat = zcalloc(sizeof(char) * 220); // XXX
if (!cpat) {
asprintf(errstr, "Can not allocate memory");
return -1;
}
p = cpat;
@ -195,8 +203,8 @@ void r3_tree_compile_patterns(node * n) {
n->combined_pattern = cpat;
const char *error;
int erroffset;
const char *pcre_error;
int pcre_erroffset;
unsigned int option_bits = 0;
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->combined_pattern, /* the pattern */
option_bits, /* default options */
&error, /* for error message */
&erroffset, /* for error offset */
&pcre_error, /* for error message */
&pcre_erroffset, /* for error offset */
NULL); /* use default character tables */
if (n->pcre_pattern == NULL) {
printf("PCRE compilation failed at offset %d: %s, pattern: %s\n", erroffset, error, n->combined_pattern);
return;
if (errstr) {
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
if (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) {
printf("PCRE study failed at offset %s\n", error);
return;
if (errstr) {
asprintf(errstr, "PCRE study failed at offset %s\n", pcre_error);
}
return -1;
}
#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);
MEASURE(tree_compile)
r3_tree_compile(n);
r3_tree_compile(n, NULL);
END_MEASURE(tree_compile)
node *m;
@ -466,7 +466,7 @@ r3_tree_insert_path(n, "/garply/grault/corge", NULL);
node * tree2 = r3_tree_create(1);
r3_tree_insert_path(tree2, "/post/{year}/{month}", NULL);
r3_tree_compile(tree2);
r3_tree_compile(tree2, NULL);
BENCHMARK(pcre_dispatch)
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/bar", NULL);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
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, "/post/{title:\\w+}", NULL);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
r3_tree_render_file(n, "png", "check_gvc.png");
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, "/foo", NULL);
r3_tree_insert_path(n, "/bar", NULL);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
return n;
}
@ -67,8 +67,8 @@ START_TEST (test_compile)
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
r3_tree_compile(n, NULL);
r3_tree_compile(n, NULL); // test double compile
r3_tree_dump(n, 0);
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, "/post/{handle:\\d+}-{id:\\d+}", NULL);
r3_tree_compile(n);
char *errstr = NULL;
r3_tree_compile(n, &errstr);
// r3_tree_dump(n, 0);
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, "/foo", NULL);
r3_tree_insert_path(n, "/bar", NULL);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
r3_tree_dump(n, 0);
node *matched;
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, "/bar", NULL);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
r3_tree_dump(n, 0);
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}-{id}", NULL);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
#ifdef DEBUG
r3_tree_dump(n, 0);
@ -270,7 +273,7 @@ START_TEST(test_pcre_pattern_simple)
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_compile(n, NULL);
// r3_tree_dump(n, 0);
node *matched;
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, "/user3/{id:\\d{3}}", &var3);
r3_tree_insert_path(n, "/user", &var0);
r3_tree_compile(n);
r3_tree_compile(n, NULL);
r3_tree_dump(n, 0);
node *matched;