commit
89fb801cfd
6 changed files with 68 additions and 37 deletions
|
@ -57,7 +57,8 @@ r3_tree_insert_pathl(n ,"/post/{id}", strlen("/post/{id}") , &route_data );
|
||||||
r3_tree_insert_pathl(n, "/user/{id:\\d+}", strlen("/user/{id:\\d+}"), &route_data );
|
r3_tree_insert_pathl(n, "/user/{id:\\d+}", strlen("/user/{id:\\d+}"), &route_data );
|
||||||
|
|
||||||
// let's compile the tree!
|
// let's compile the tree!
|
||||||
r3_tree_compile(n);
|
char *errstr = NULL;
|
||||||
|
int errno = r3_tree_compile(n, &errstr);
|
||||||
|
|
||||||
|
|
||||||
// dump the compiled tree
|
// dump the compiled tree
|
||||||
|
@ -108,7 +109,9 @@ int route_data = 3;
|
||||||
// insert the route path into the router tree
|
// insert the route path into the router tree
|
||||||
r3_tree_insert_routel(n, METHOD_GET | METHOD_POST, "/blog/post", sizeof("/blog/post") - 1, &route_data );
|
r3_tree_insert_routel(n, METHOD_GET | METHOD_POST, "/blog/post", sizeof("/blog/post") - 1, &route_data );
|
||||||
|
|
||||||
r3_tree_compile(n);
|
char *errstr = NULL;
|
||||||
|
int errno;
|
||||||
|
errno = r3_tree_compile(n, &errstr);
|
||||||
|
|
||||||
|
|
||||||
// in your http server handler
|
// in your http server handler
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
45
src/node.c
45
src/node.c
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
#include "r3.h"
|
#include "r3.h"
|
||||||
#include "r3_str.h"
|
#include "r3_str.h"
|
||||||
#include "zmalloc.h"
|
#include "zmalloc.h"
|
||||||
|
@ -47,7 +48,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,20 +56,20 @@ static node * create_simple_str_tree() {
|
||||||
|
|
||||||
START_TEST (test_compile)
|
START_TEST (test_compile)
|
||||||
{
|
{
|
||||||
str_array *t;
|
node *n;
|
||||||
node * n = create_simple_str_tree();
|
|
||||||
|
|
||||||
node *m;
|
node *m;
|
||||||
edge *e;
|
edge *e;
|
||||||
|
|
||||||
|
n = create_simple_str_tree();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
r3_tree_dump(n, 0);
|
r3_tree_dump(n, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
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 +105,13 @@ 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;
|
||||||
|
int errno;
|
||||||
|
errno = r3_tree_compile(n, &errstr);
|
||||||
|
ck_assert(errno == 0); // no error
|
||||||
|
|
||||||
// r3_tree_dump(n, 0);
|
// r3_tree_dump(n, 0);
|
||||||
|
|
||||||
node *matched;
|
node *matched;
|
||||||
|
@ -131,7 +138,10 @@ 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);
|
|
||||||
|
char *errstr = NULL;
|
||||||
|
r3_tree_compile(n, &errstr);
|
||||||
|
|
||||||
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 +166,10 @@ 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);
|
|
||||||
|
char *errstr = NULL;
|
||||||
|
r3_tree_compile(n, &errstr);
|
||||||
|
|
||||||
r3_tree_dump(n, 0);
|
r3_tree_dump(n, 0);
|
||||||
node *matched;
|
node *matched;
|
||||||
|
|
||||||
|
@ -202,7 +215,9 @@ 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);
|
|
||||||
|
char * errstr = NULL;
|
||||||
|
r3_tree_compile(n, &errstr);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
r3_tree_dump(n, 0);
|
r3_tree_dump(n, 0);
|
||||||
|
@ -270,7 +285,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 +317,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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue