Add route namespace
Summary: type route now becomes R3Route Related issue #63
This commit is contained in:
parent
29a2a934d0
commit
c3ef959539
11 changed files with 76 additions and 76 deletions
20
README.md
20
README.md
|
@ -6,7 +6,7 @@ R3
|
||||||
[![Coverage Status](https://coveralls.io/repos/c9s/r3/badge.svg)](https://coveralls.io/r/c9s/r3)
|
[![Coverage Status](https://coveralls.io/repos/c9s/r3/badge.svg)](https://coveralls.io/r/c9s/r3)
|
||||||
|
|
||||||
R3 is an URL router library with high performance, thus, it's implemented in C.
|
R3 is an URL router library with high performance, thus, it's implemented in C.
|
||||||
It compiles your route paths into a prefix trie.
|
It compiles your R3Route paths into a prefix trie.
|
||||||
|
|
||||||
By using the prefix tree constructed in the start-up time, you can dispatch
|
By using the prefix tree constructed in the start-up time, you can dispatch
|
||||||
the path to the controller with high efficiency.
|
the path to the controller with high efficiency.
|
||||||
|
@ -47,7 +47,7 @@ R3Node *n = r3_tree_create(10);
|
||||||
|
|
||||||
int route_data = 3;
|
int route_data = 3;
|
||||||
|
|
||||||
// insert the route path into the router tree
|
// insert the R3Route path into the router tree
|
||||||
r3_tree_insert_path(n, "/bar", &route_data); // ignore the length of path
|
r3_tree_insert_path(n, "/bar", &route_data); // ignore the length of path
|
||||||
|
|
||||||
r3_tree_insert_pathl(n, "/zoo", strlen("/zoo"), &route_data );
|
r3_tree_insert_pathl(n, "/zoo", strlen("/zoo"), &route_data );
|
||||||
|
@ -114,7 +114,7 @@ entry->request_method = METHOD_POST;
|
||||||
entry->request_method = METHOD_GET | METHOD_POST;
|
entry->request_method = METHOD_GET | METHOD_POST;
|
||||||
```
|
```
|
||||||
|
|
||||||
When using `match_entry`, you may match the route with `r3_tree_match_entry` function:
|
When using `match_entry`, you may match the R3Route with `r3_tree_match_entry` function:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
R3Node * matched_node = r3_tree_match_entry(n, entry);
|
R3Node * matched_node = r3_tree_match_entry(n, entry);
|
||||||
|
@ -141,7 +141,7 @@ n = r3_tree_create(10);
|
||||||
|
|
||||||
int route_data = 3;
|
int route_data = 3;
|
||||||
|
|
||||||
// insert the route path into the router tree
|
// insert the R3Route 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 );
|
||||||
|
|
||||||
char *errstr = NULL;
|
char *errstr = NULL;
|
||||||
|
@ -160,7 +160,7 @@ match_entry * entry = match_entry_create("/blog/post");
|
||||||
entry->request_method = METHOD_GET;
|
entry->request_method = METHOD_GET;
|
||||||
|
|
||||||
|
|
||||||
route *matched_route = r3_tree_match_route(n, entry);
|
R3Route *matched_R3Route = r3_tree_match_route(n, entry);
|
||||||
matched_route->data; // get the data from matched route
|
matched_route->data; // get the data from matched route
|
||||||
|
|
||||||
// free the objects at the end
|
// free the objects at the end
|
||||||
|
@ -179,7 +179,7 @@ To specify the pattern of a slug, you may write a colon to separate the slug nam
|
||||||
|
|
||||||
"/user/{userId:\\d+}"
|
"/user/{userId:\\d+}"
|
||||||
|
|
||||||
The above route will use `\d+` as its pattern.
|
The above R3Route will use `\d+` as its pattern.
|
||||||
|
|
||||||
|
|
||||||
Optimization
|
Optimization
|
||||||
|
@ -206,7 +206,7 @@ And here is the result of the router journey:
|
||||||
|
|
||||||
omg 9932.9 (±4.8%) i/s - 49873 in 5.033452s
|
omg 9932.9 (±4.8%) i/s - 49873 in 5.033452s
|
||||||
|
|
||||||
r3 uses the same route path data for benchmarking, and here is the benchmark:
|
r3 uses the same R3Route path data for benchmarking, and here is the benchmark:
|
||||||
|
|
||||||
3 runs, 5000000 iterations each run, finished in 1.308894 seconds
|
3 runs, 5000000 iterations each run, finished in 1.308894 seconds
|
||||||
11460057.83 i/sec
|
11460057.83 i/sec
|
||||||
|
@ -214,7 +214,7 @@ r3 uses the same route path data for benchmarking, and here is the benchmark:
|
||||||
|
|
||||||
### The Route Paths Of Benchmark
|
### The Route Paths Of Benchmark
|
||||||
|
|
||||||
The route path generator is from <https://github.com/stevegraham/rails/pull/1>:
|
The R3Route path generator is from <https://github.com/stevegraham/rails/pull/1>:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
@ -242,7 +242,7 @@ Function prefix mapping
|
||||||
Rendering Routes With Graphviz
|
Rendering Routes With Graphviz
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
|
||||||
The `r3_tree_render_file` API let you render the whole route trie into a image.
|
The `r3_tree_render_file` API let you render the whole R3Route trie into a image.
|
||||||
|
|
||||||
To use graphviz, you need to enable graphviz while you run `configure`:
|
To use graphviz, you need to enable graphviz while you run `configure`:
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ $ret = r3_dispatch($rs, '/blog/post/3' );
|
||||||
list($complete, $route, $variables) = $ret;
|
list($complete, $route, $variables) = $ret;
|
||||||
|
|
||||||
// matched conditions aren't done yet
|
// matched conditions aren't done yet
|
||||||
list($error, $message) = r3_validate($route); // validate route conditions
|
list($error, $message) = r3_validate($route); // validate R3Route conditions
|
||||||
if ( $error ) {
|
if ( $error ) {
|
||||||
echo $message; // "Method not allowed", "...";
|
echo $message; // "Method not allowed", "...";
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ Architecture: any
|
||||||
Depends: libr3 (= ${binary:Version})
|
Depends: libr3 (= ${binary:Version})
|
||||||
Description: Development files for libr3
|
Description: Development files for libr3
|
||||||
libr3 (https://github.com/c9s/r3) is an URL router library with high
|
libr3 (https://github.com/c9s/r3) is an URL router library with high
|
||||||
performance, thus, it's implemented in C. It compiles your route paths into
|
performance, thus, it's implemented in C. It compiles your R3Route paths into
|
||||||
a prefix trie.
|
a prefix trie.
|
||||||
.
|
.
|
||||||
This package contains header files for libr3.
|
This package contains header files for libr3.
|
||||||
|
@ -24,5 +24,5 @@ Architecture: any
|
||||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
Description: High performance URL routing library written in C.
|
Description: High performance URL routing library written in C.
|
||||||
libr3 (https://github.com/c9s/r3) is an URL router library with high
|
libr3 (https://github.com/c9s/r3) is an URL router library with high
|
||||||
performance, thus, it's implemented in C. It compiles your route paths into
|
performance, thus, it's implemented in C. It compiles your R3Route paths into
|
||||||
a prefix trie.
|
a prefix trie.
|
||||||
|
|
|
@ -9,7 +9,7 @@ void example_1() {
|
||||||
// create a router tree with 10 children capacity (this capacity can grow dynamically)
|
// create a router tree with 10 children capacity (this capacity can grow dynamically)
|
||||||
r3::Tree tree(10);
|
r3::Tree tree(10);
|
||||||
|
|
||||||
// insert the route path into the router tree
|
// insert the R3Route path into the router tree
|
||||||
int route_data_1 = 1;
|
int route_data_1 = 1;
|
||||||
tree.insert_path("/bar", &route_data_1); // ignore the length of path
|
tree.insert_path("/bar", &route_data_1); // ignore the length of path
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ void example_2() {
|
||||||
// create a router tree with 10 children capacity (this capacity can grow dynamically)
|
// create a router tree with 10 children capacity (this capacity can grow dynamically)
|
||||||
r3::Tree tree(10);
|
r3::Tree tree(10);
|
||||||
|
|
||||||
// insert the route path into the router tree
|
// insert the R3Route path into the router tree
|
||||||
int route_data = 1;
|
int route_data = 1;
|
||||||
tree.insert_routel(METHOD_GET | METHOD_POST, "/blog/post",
|
tree.insert_routel(METHOD_GET | METHOD_POST, "/blog/post",
|
||||||
sizeof("/blog/post") - 1, &route_data);
|
sizeof("/blog/post") - 1, &route_data);
|
||||||
|
|
28
include/r3.h
28
include/r3.h
|
@ -43,7 +43,7 @@ struct _node;
|
||||||
struct _route;
|
struct _route;
|
||||||
typedef struct _edge R3Edge;
|
typedef struct _edge R3Edge;
|
||||||
typedef struct _node R3Node;
|
typedef struct _node R3Node;
|
||||||
typedef struct _route route;
|
typedef struct _R3Route R3Route;
|
||||||
|
|
||||||
struct _node {
|
struct _node {
|
||||||
R3Edge * edges;
|
R3Edge * edges;
|
||||||
|
@ -58,8 +58,8 @@ struct _node {
|
||||||
unsigned int ov_cnt; // capture vector array size for pcre
|
unsigned int ov_cnt; // capture vector array size for pcre
|
||||||
|
|
||||||
|
|
||||||
route ** routes;
|
R3Route ** routes;
|
||||||
// the pointer of route data
|
// the pointer of R3Route data
|
||||||
void * data;
|
void * data;
|
||||||
|
|
||||||
// almost less than 255
|
// almost less than 255
|
||||||
|
@ -79,7 +79,7 @@ struct _edge {
|
||||||
unsigned int has_slug; // 4byte
|
unsigned int has_slug; // 4byte
|
||||||
} __attribute__((aligned(64)));
|
} __attribute__((aligned(64)));
|
||||||
|
|
||||||
struct _route {
|
struct _R3Route {
|
||||||
char * path;
|
char * path;
|
||||||
int path_len;
|
int path_len;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ typedef struct {
|
||||||
int path_len; // the length of the current path
|
int path_len; // the length of the current path
|
||||||
int request_method; // current request method
|
int request_method; // current request method
|
||||||
|
|
||||||
void * data; // route ptr
|
void * data; // R3Route ptr
|
||||||
|
|
||||||
char * host; // the request host
|
char * host; // the request host
|
||||||
int host_len;
|
int host_len;
|
||||||
|
@ -138,9 +138,9 @@ R3Node * r3_tree_insert_pathl(R3Node *tree, const char *path, int path_len, void
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
route * r3_tree_insert_routel(R3Node * tree, int method, const char *path, int path_len, void *data);
|
R3Route * r3_tree_insert_routel(R3Node * tree, int method, const char *path, int path_len, void *data);
|
||||||
|
|
||||||
route * r3_tree_insert_routel_ex(R3Node * tree, int method, const char *path, int path_len, void *data, char **errstr);
|
R3Route * r3_tree_insert_routel_ex(R3Node * tree, int method, const char *path, int path_len, void *data, char **errstr);
|
||||||
|
|
||||||
#define r3_tree_insert_routel(n, method, path, path_len, data) r3_tree_insert_routel_ex(n, method, path, path_len, data, NULL)
|
#define r3_tree_insert_routel(n, method, path, path_len, data) r3_tree_insert_routel_ex(n, method, path, path_len, data, NULL)
|
||||||
|
|
||||||
|
@ -152,7 +152,7 @@ route * r3_tree_insert_routel_ex(R3Node * tree, int method, const char *path, in
|
||||||
/**
|
/**
|
||||||
* The private API to insert a path
|
* The private API to insert a path
|
||||||
*/
|
*/
|
||||||
R3Node * r3_tree_insert_pathl_ex(R3Node *tree, const char *path, int path_len, route * route, void * data, char ** errstr);
|
R3Node * r3_tree_insert_pathl_ex(R3Node *tree, const char *path, int path_len, R3Route * route, void * data, char ** errstr);
|
||||||
|
|
||||||
void r3_tree_dump(const R3Node * n, int level);
|
void r3_tree_dump(const R3Node * n, int level);
|
||||||
|
|
||||||
|
@ -185,18 +185,18 @@ void r3_edge_free(R3Edge * edge);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
route * r3_route_create(const char * path);
|
R3Route * r3_route_create(const char * path);
|
||||||
|
|
||||||
route * r3_route_createl(const char * path, int path_len);
|
R3Route * r3_route_createl(const char * path, int path_len);
|
||||||
|
|
||||||
|
|
||||||
void r3_node_append_route(R3Node * n, route * route);
|
void r3_node_append_route(R3Node * n, R3Route * route);
|
||||||
|
|
||||||
void r3_route_free(route * route);
|
void r3_route_free(R3Route * route);
|
||||||
|
|
||||||
int r3_route_cmp(const route *r1, const match_entry *r2);
|
int r3_route_cmp(const R3Route *r1, const match_entry *r2);
|
||||||
|
|
||||||
route * r3_tree_match_route(const R3Node *n, match_entry * entry);
|
R3Route * r3_tree_match_route(const R3Node *n, match_entry * entry);
|
||||||
|
|
||||||
#define r3_route_create(p) r3_route_createl(p, strlen(p))
|
#define r3_route_create(p) r3_route_createl(p, strlen(p))
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace r3 {
|
||||||
T* p_;
|
T* p_;
|
||||||
};
|
};
|
||||||
typedef Base<R3Node> Node;
|
typedef Base<R3Node> Node;
|
||||||
typedef Base<route> Route;
|
typedef Base<R3Route> Route;
|
||||||
|
|
||||||
class MatchEntry : public Base<match_entry> {
|
class MatchEntry : public Base<match_entry> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
|
|
||||||
json_object * r3_edge_to_json_object(const edge * e);
|
json_object * r3_edge_to_json_object(const edge * e);
|
||||||
json_object * r3_node_to_json_object(const node * n);
|
json_object * r3_node_to_json_object(const node * n);
|
||||||
json_object * r3_route_to_json_object(const route * r);
|
json_object * r3_route_to_json_object(const R3Route * r);
|
||||||
|
|
||||||
const char * r3_node_to_json_string_ext(const node * n, int options);
|
const char * r3_node_to_json_string_ext(const node * n, int options);
|
||||||
const char * r3_node_to_json_pretty_string(const node * n);
|
const char * r3_node_to_json_pretty_string(const node * n);
|
||||||
|
|
|
@ -407,8 +407,8 @@ PHP_FUNCTION(r3_match)
|
||||||
}
|
}
|
||||||
|
|
||||||
zval *z_route;
|
zval *z_route;
|
||||||
z_route = php_r3_match(z_routes, path, path_len TSRMLS_CC);
|
z_R3Route = php_r3_match(z_routes, path, path_len TSRMLS_CC);
|
||||||
if ( z_route != NULL ) {
|
if ( z_R3Route != NULL ) {
|
||||||
*return_value = *z_route;
|
*return_value = *z_route;
|
||||||
zval_copy_ctor(return_value);
|
zval_copy_ctor(return_value);
|
||||||
return;
|
return;
|
||||||
|
@ -438,7 +438,7 @@ PHP_FUNCTION(r3_persistent_dispatch)
|
||||||
char *ns, *filename, *path;
|
char *ns, *filename, *path;
|
||||||
int ns_len, filename_len, path_len;
|
int ns_len, filename_len, path_len;
|
||||||
zval *mux = NULL;
|
zval *mux = NULL;
|
||||||
zval *route = NULL;
|
zval *R3Route = NULL;
|
||||||
zval *z_path = NULL;
|
zval *z_path = NULL;
|
||||||
|
|
||||||
/* parse parameters */
|
/* parse parameters */
|
||||||
|
@ -463,15 +463,15 @@ PHP_FUNCTION(r3_persistent_dispatch)
|
||||||
ZVAL_STRINGL(z_path, path ,path_len, 1); // no copy
|
ZVAL_STRINGL(z_path, path ,path_len, 1); // no copy
|
||||||
|
|
||||||
// XXX: pass return_value to the method call, so we don't need to copy
|
// XXX: pass return_value to the method call, so we don't need to copy
|
||||||
route = call_mux_method(mux, "dispatch" , sizeof("dispatch"), 1 , z_path, NULL, NULL TSRMLS_CC);
|
R3Route = call_mux_method(mux, "dispatch" , sizeof("dispatch"), 1 , z_path, NULL, NULL TSRMLS_CC);
|
||||||
zval_ptr_dtor(&z_path);
|
zval_ptr_dtor(&z_path);
|
||||||
|
|
||||||
if ( route ) {
|
if ( R3Route ) {
|
||||||
*return_value = *route;
|
*return_value = *route;
|
||||||
zval_copy_ctor(return_value);
|
zval_copy_ctor(return_value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// route not found
|
// R3Route not found
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,7 +649,7 @@ inline zval * php_r3_match(zval *z_routes, char *path, int path_len TSRMLS_DC) {
|
||||||
|
|
||||||
// tell garbage collector to collect it, we need to use pcre_subpats later.
|
// tell garbage collector to collect it, we need to use pcre_subpats later.
|
||||||
|
|
||||||
// check conditions only when route option is provided
|
// check conditions only when R3Route option is provided
|
||||||
if ( zend_hash_index_find( Z_ARRVAL_PP(z_route_pp), 3, (void**) &z_route_options_pp) == SUCCESS ) {
|
if ( zend_hash_index_find( Z_ARRVAL_PP(z_route_pp), 3, (void**) &z_route_options_pp) == SUCCESS ) {
|
||||||
if ( zend_hash_num_elements(Z_ARRVAL_PP(z_route_options_pp)) ) {
|
if ( zend_hash_num_elements(Z_ARRVAL_PP(z_route_options_pp)) ) {
|
||||||
if ( 0 == validate_request_method( z_route_options_pp, current_request_method TSRMLS_CC) ) {
|
if ( 0 == validate_request_method( z_route_options_pp, current_request_method TSRMLS_CC) ) {
|
||||||
|
|
|
@ -81,7 +81,7 @@ zend_class_entry ** get_pattern_compiler_ce(TSRMLS_D) {
|
||||||
return ce_pattern_compiler;
|
return ce_pattern_compiler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns compiled route zval
|
// Returns compiled R3Route zval
|
||||||
zval * compile_route_pattern(zval *z_pattern, zval *z_options, zend_class_entry **ce_pattern_compiler TSRMLS_DC)
|
zval * compile_route_pattern(zval *z_pattern, zval *z_options, zend_class_entry **ce_pattern_compiler TSRMLS_DC)
|
||||||
{
|
{
|
||||||
// zend_class_entry **ce_pattern_compiler;
|
// zend_class_entry **ce_pattern_compiler;
|
||||||
|
@ -92,10 +92,10 @@ zval * compile_route_pattern(zval *z_pattern, zval *z_options, zend_class_entry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zval *z_compiled_route = NULL; // will be an array
|
zval *z_compiled_R3Route = NULL; // will be an array
|
||||||
zend_call_method( NULL, *ce_pattern_compiler, NULL, "compile", strlen("compile"), &z_compiled_route, 2, z_pattern, z_options TSRMLS_CC );
|
zend_call_method( NULL, *ce_pattern_compiler, NULL, "compile", strlen("compile"), &z_compiled_route, 2, z_pattern, z_options TSRMLS_CC );
|
||||||
|
|
||||||
if ( z_compiled_route == NULL ) {
|
if ( z_compiled_R3Route == NULL ) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else if ( Z_TYPE_P(z_compiled_route) == IS_NULL ) {
|
} else if ( Z_TYPE_P(z_compiled_route) == IS_NULL ) {
|
||||||
zval_ptr_dtor(&z_compiled_route);
|
zval_ptr_dtor(&z_compiled_route);
|
||||||
|
@ -467,7 +467,7 @@ PHP_METHOD(Mux, mount) {
|
||||||
// zval for new route
|
// zval for new route
|
||||||
zval *z_new_routes;
|
zval *z_new_routes;
|
||||||
|
|
||||||
// zval for route item
|
// zval for R3Route item
|
||||||
zval **z_is_pcre; // route[0]
|
zval **z_is_pcre; // route[0]
|
||||||
zval **z_route_pattern;
|
zval **z_route_pattern;
|
||||||
zval **z_route_callback;
|
zval **z_route_callback;
|
||||||
|
@ -514,10 +514,10 @@ PHP_METHOD(Mux, mount) {
|
||||||
|
|
||||||
// $routeArgs = PatternCompiler::compile($newPattern,
|
// $routeArgs = PatternCompiler::compile($newPattern,
|
||||||
// array_merge_recursive($route[3], $options) );
|
// array_merge_recursive($route[3], $options) );
|
||||||
zval *z_compiled_route = compile_route_pattern(z_new_pattern, *z_route_options, ce_pattern_compiler TSRMLS_CC);
|
zval *z_compiled_R3Route = compile_route_pattern(z_new_pattern, *z_route_options, ce_pattern_compiler TSRMLS_CC);
|
||||||
|
|
||||||
|
|
||||||
if ( z_compiled_route == NULL || Z_TYPE_P(z_compiled_route) == IS_NULL ) {
|
if ( z_compiled_R3Route == NULL || Z_TYPE_P(z_compiled_route) == IS_NULL ) {
|
||||||
php_error( E_ERROR, "Cannot compile pattern: %s", new_pattern);
|
php_error( E_ERROR, "Cannot compile pattern: %s", new_pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -535,7 +535,7 @@ PHP_METHOD(Mux, mount) {
|
||||||
Z_ADDREF_P(z_compiled_route);
|
Z_ADDREF_P(z_compiled_route);
|
||||||
Z_ADDREF_P(z_new_routes);
|
Z_ADDREF_P(z_new_routes);
|
||||||
|
|
||||||
// create new route and append to mux->routes
|
// create new R3Route and append to mux->routes
|
||||||
add_index_bool(z_new_routes, 0 , 1); // pcre flag == false
|
add_index_bool(z_new_routes, 0 , 1); // pcre flag == false
|
||||||
add_index_zval(z_new_routes, 1, *z_compiled_route_pattern);
|
add_index_zval(z_new_routes, 1, *z_compiled_route_pattern);
|
||||||
add_index_zval(z_new_routes, 2 , *z_route_callback);
|
add_index_zval(z_new_routes, 2 , *z_route_callback);
|
||||||
|
@ -558,7 +558,7 @@ PHP_METHOD(Mux, mount) {
|
||||||
|
|
||||||
int new_pattern_len = pattern_len + Z_STRLEN_PP(z_route_pattern);
|
int new_pattern_len = pattern_len + Z_STRLEN_PP(z_route_pattern);
|
||||||
|
|
||||||
// Merge the mount options with the route options
|
// Merge the mount options with the R3Route options
|
||||||
zval *z_new_route_options;
|
zval *z_new_route_options;
|
||||||
MAKE_STD_ZVAL(z_new_route_options);
|
MAKE_STD_ZVAL(z_new_route_options);
|
||||||
array_init(z_new_route_options);
|
array_init(z_new_route_options);
|
||||||
|
@ -681,11 +681,11 @@ PHP_METHOD(Mux, getRoute) {
|
||||||
}
|
}
|
||||||
|
|
||||||
zval *z_routes_by_id = NULL;
|
zval *z_routes_by_id = NULL;
|
||||||
zval **z_route = NULL;
|
zval **z_R3Route = NULL;
|
||||||
z_routes_by_id = zend_read_property( ce_r3_mux , this_ptr, "routesById", sizeof("routesById")-1, 1 TSRMLS_CC);
|
z_routes_by_id = zend_read_property( ce_r3_mux , this_ptr, "routesById", sizeof("routesById")-1, 1 TSRMLS_CC);
|
||||||
|
|
||||||
// php_var_dump(&z_routes_by_id, 1 TSRMLS_CC);
|
// php_var_dump(&z_routes_by_id, 1 TSRMLS_CC);
|
||||||
if ( zend_hash_find( Z_ARRVAL_P(z_routes_by_id) , route_id, route_id_len + 1, (void**) &z_route ) == SUCCESS ) {
|
if ( zend_hash_find( Z_ARRVAL_P(z_routes_by_id) , route_id, route_id_len + 1, (void**) &z_R3Route ) == SUCCESS ) {
|
||||||
*return_value = **z_route;
|
*return_value = **z_route;
|
||||||
zval_copy_ctor(return_value);
|
zval_copy_ctor(return_value);
|
||||||
return;
|
return;
|
||||||
|
@ -788,7 +788,7 @@ PHP_METHOD(Mux, compile) {
|
||||||
zend_call_method( NULL, NULL, NULL, "usort", strlen("usort"), &rv, 2,
|
zend_call_method( NULL, NULL, NULL, "usort", strlen("usort"), &rv, 2,
|
||||||
z_routes, z_sort_callback TSRMLS_CC );
|
z_routes, z_sort_callback TSRMLS_CC );
|
||||||
zval_ptr_dtor(&z_sort_callback); // recycle sort callback zval
|
zval_ptr_dtor(&z_sort_callback); // recycle sort callback zval
|
||||||
// php_error(E_ERROR,"route sort failed.");
|
// php_error(E_ERROR,"R3Route sort failed.");
|
||||||
// zend_update_property(ce_r3_mux, getThis(), "routes", sizeof("routes")-1, z_routes TSRMLS_CC);
|
// zend_update_property(ce_r3_mux, getThis(), "routes", sizeof("routes")-1, z_routes TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -843,7 +843,7 @@ PHP_METHOD(Mux, dispatch) {
|
||||||
int path_len;
|
int path_len;
|
||||||
zval *z_path;
|
zval *z_path;
|
||||||
|
|
||||||
zval *z_return_route = NULL;
|
zval *z_return_R3Route = NULL;
|
||||||
|
|
||||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &path, &path_len) == FAILURE) {
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
|
@ -856,7 +856,7 @@ PHP_METHOD(Mux, dispatch) {
|
||||||
zend_hash_quick_find( &ce_r3_mux->function_table, "match", sizeof("match"), zend_inline_hash_func(ZEND_STRS("match")), (void **) &fe);
|
zend_hash_quick_find( &ce_r3_mux->function_table, "match", sizeof("match"), zend_inline_hash_func(ZEND_STRS("match")), (void **) &fe);
|
||||||
zend_call_method( &this_ptr, ce_r3_mux, &fe, "match", strlen("match"), &z_return_route, 1, z_path, NULL TSRMLS_CC );
|
zend_call_method( &this_ptr, ce_r3_mux, &fe, "match", strlen("match"), &z_return_route, 1, z_path, NULL TSRMLS_CC );
|
||||||
|
|
||||||
if ( ! z_return_route || Z_TYPE_P(z_return_route) == IS_NULL ) {
|
if ( ! z_return_R3Route || Z_TYPE_P(z_return_route) == IS_NULL ) {
|
||||||
zval_ptr_dtor(&z_path);
|
zval_ptr_dtor(&z_path);
|
||||||
RETURN_NULL();
|
RETURN_NULL();
|
||||||
}
|
}
|
||||||
|
@ -908,11 +908,11 @@ PHP_METHOD(Mux, dispatch) {
|
||||||
zval *z_substr;
|
zval *z_substr;
|
||||||
|
|
||||||
if ( zend_hash_quick_find( Z_ARRVAL_PP(z_options) , "vars", sizeof("vars"), zend_inline_hash_func(ZEND_STRS("vars")), (void**) &z_route_vars ) == FAILURE ) {
|
if ( zend_hash_quick_find( Z_ARRVAL_PP(z_options) , "vars", sizeof("vars"), zend_inline_hash_func(ZEND_STRS("vars")), (void**) &z_route_vars ) == FAILURE ) {
|
||||||
php_error(E_ERROR, "require route vars");
|
php_error(E_ERROR, "require R3Route vars");
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
if ( zend_hash_index_find( Z_ARRVAL_PP(z_options) , 0 , (void**) &z_route_vars_0 ) == FAILURE ) {
|
if ( zend_hash_index_find( Z_ARRVAL_PP(z_options) , 0 , (void**) &z_route_vars_0 ) == FAILURE ) {
|
||||||
php_error(E_ERROR, "require route vars[0]");
|
php_error(E_ERROR, "require R3Route vars[0]");
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -955,7 +955,7 @@ PHP_METHOD(Mux, dispatch) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( z_return_route ) {
|
if ( z_return_R3Route ) {
|
||||||
*return_value = *z_return_route;
|
*return_value = *z_return_route;
|
||||||
zval_copy_ctor(return_value);
|
zval_copy_ctor(return_value);
|
||||||
}
|
}
|
||||||
|
@ -972,7 +972,7 @@ PHP_METHOD(Mux, match) {
|
||||||
}
|
}
|
||||||
|
|
||||||
zval **z_route_pp = NULL;
|
zval **z_route_pp = NULL;
|
||||||
zval *z_route = NULL;
|
zval *z_R3Route = NULL;
|
||||||
if ( zend_hash_find( Z_ARRVAL_P( zend_read_property(ce_r3_mux, this_ptr, "staticRoutes", sizeof("staticRoutes") - 1, 1 TSRMLS_CC) ), path, path_len, (void**)&z_route_pp) == SUCCESS ) {
|
if ( zend_hash_find( Z_ARRVAL_P( zend_read_property(ce_r3_mux, this_ptr, "staticRoutes", sizeof("staticRoutes") - 1, 1 TSRMLS_CC) ), path, path_len, (void**)&z_route_pp) == SUCCESS ) {
|
||||||
if ( Z_TYPE_PP(z_route_pp) != IS_NULL ) {
|
if ( Z_TYPE_PP(z_route_pp) != IS_NULL ) {
|
||||||
*return_value = **z_route_pp;
|
*return_value = **z_route_pp;
|
||||||
|
@ -981,8 +981,8 @@ PHP_METHOD(Mux, match) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
z_route = php_r3_match(zend_read_property(ce_r3_mux , this_ptr , "routes", sizeof("routes")-1, 1 TSRMLS_CC), path, path_len TSRMLS_CC);
|
z_R3Route = php_r3_match(zend_read_property(ce_r3_mux , this_ptr , "routes", sizeof("routes")-1, 1 TSRMLS_CC), path, path_len TSRMLS_CC);
|
||||||
if ( z_route != NULL ) {
|
if ( z_R3Route != NULL ) {
|
||||||
*return_value = *z_route;
|
*return_value = *z_route;
|
||||||
zval_copy_ctor(return_value);
|
zval_copy_ctor(return_value);
|
||||||
Z_ADDREF_P(z_route);
|
Z_ADDREF_P(z_route);
|
||||||
|
@ -1058,7 +1058,7 @@ PHP_METHOD(Mux, appendPCRERoute) {
|
||||||
zend_call_method( NULL, *ce_pattern_compiler, NULL, "compile", strlen("compile"), &rv, 1, z_pattern, NULL TSRMLS_CC );
|
zend_call_method( NULL, *ce_pattern_compiler, NULL, "compile", strlen("compile"), &rv, 1, z_pattern, NULL TSRMLS_CC );
|
||||||
|
|
||||||
if ( rv == NULL || Z_TYPE_P(rv) == IS_NULL ) {
|
if ( rv == NULL || Z_TYPE_P(rv) == IS_NULL ) {
|
||||||
zend_throw_exception(ce_r3_exception, "Can not compile route pattern", 0 TSRMLS_CC);
|
zend_throw_exception(ce_r3_exception, "Can not compile R3Route pattern", 0 TSRMLS_CC);
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
add_next_index_zval(z_routes, rv);
|
add_next_index_zval(z_routes, rv);
|
||||||
|
@ -1115,9 +1115,9 @@ inline void mux_add_route(INTERNAL_FUNCTION_PARAMETERS)
|
||||||
MAKE_STD_ZVAL(z_pattern);
|
MAKE_STD_ZVAL(z_pattern);
|
||||||
ZVAL_STRINGL(z_pattern, pattern, pattern_len, 1);
|
ZVAL_STRINGL(z_pattern, pattern, pattern_len, 1);
|
||||||
|
|
||||||
zval *z_compiled_route = compile_route_pattern(z_pattern, z_options, NULL TSRMLS_CC);
|
zval *z_compiled_R3Route = compile_route_pattern(z_pattern, z_options, NULL TSRMLS_CC);
|
||||||
if ( z_compiled_route == NULL ) {
|
if ( z_compiled_R3Route == NULL ) {
|
||||||
zend_throw_exception(ce_r3_exception, "Unable to compile route pattern.", 0 TSRMLS_CC);
|
zend_throw_exception(ce_r3_exception, "Unable to compile R3Route pattern.", 0 TSRMLS_CC);
|
||||||
RETURN_FALSE;
|
RETURN_FALSE;
|
||||||
}
|
}
|
||||||
zval_ptr_dtor(&z_pattern);
|
zval_ptr_dtor(&z_pattern);
|
||||||
|
@ -1160,7 +1160,7 @@ inline void mux_add_route(INTERNAL_FUNCTION_PARAMETERS)
|
||||||
add_index_zval( z_new_route, 3 , z_options);
|
add_index_zval( z_new_route, 3 , z_options);
|
||||||
add_next_index_zval(z_routes, z_new_route);
|
add_next_index_zval(z_routes, z_new_route);
|
||||||
|
|
||||||
// if there is no option specified in z_options, we can add the route to our static route hash
|
// if there is no option specified in z_options, we can add the R3Route to our static R3Route hash
|
||||||
if ( zend_hash_num_elements(Z_ARRVAL_P(z_options)) ) {
|
if ( zend_hash_num_elements(Z_ARRVAL_P(z_options)) ) {
|
||||||
zval * z_static_routes = zend_read_property(ce_r3_mux, this_ptr, "staticRoutes", sizeof("staticRoutes")-1, 1 TSRMLS_CC);
|
zval * z_static_routes = zend_read_property(ce_r3_mux, this_ptr, "staticRoutes", sizeof("staticRoutes")-1, 1 TSRMLS_CC);
|
||||||
if ( z_static_routes ) {
|
if ( z_static_routes ) {
|
||||||
|
@ -1173,7 +1173,7 @@ inline void mux_add_route(INTERNAL_FUNCTION_PARAMETERS)
|
||||||
zval * z_routes_by_id = zend_read_property(ce_r3_mux, this_ptr, "routesById", sizeof("routesById")-1, 1 TSRMLS_CC);
|
zval * z_routes_by_id = zend_read_property(ce_r3_mux, this_ptr, "routesById", sizeof("routesById")-1, 1 TSRMLS_CC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
zval *id_route = NULL;
|
zval *id_R3Route = NULL;
|
||||||
ALLOC_ZVAL(id_route);
|
ALLOC_ZVAL(id_route);
|
||||||
ZVAL_COPY_VALUE(id_route, z_new_route);
|
ZVAL_COPY_VALUE(id_route, z_new_route);
|
||||||
zval_copy_ctor(id_route);
|
zval_copy_ctor(id_route);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "r3.h"
|
#include "r3.h"
|
||||||
#include "r3_json.h"
|
#include "r3_json.h"
|
||||||
|
|
||||||
json_object * r3_route_to_json_object(const route * r) {
|
json_object * r3_route_to_json_object(const R3Route * r) {
|
||||||
json_object *obj;
|
json_object *obj;
|
||||||
|
|
||||||
obj = json_object_new_object();
|
obj = json_object_new_object();
|
||||||
|
|
22
src/node.c
22
src/node.c
|
@ -434,7 +434,7 @@ R3Node * r3_tree_matchl(const R3Node * n, const char * path, int path_len, match
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
route * r3_tree_match_route(const R3Node *tree, match_entry * entry) {
|
R3Route * r3_tree_match_route(const R3Node *tree, match_entry * entry) {
|
||||||
R3Node *n;
|
R3Node *n;
|
||||||
int i;
|
int i;
|
||||||
n = r3_tree_match_entry(tree, entry);
|
n = r3_tree_match_entry(tree, entry);
|
||||||
|
@ -483,12 +483,12 @@ R3Node * r3_node_create() {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void r3_route_free(route * route) {
|
void r3_route_free(R3Route * route) {
|
||||||
zfree(route);
|
zfree(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
route * r3_route_createl(const char * path, int path_len) {
|
R3Route * r3_route_createl(const char * path, int path_len) {
|
||||||
route * info = zmalloc(sizeof(route));
|
R3Route * info = zmalloc(sizeof(R3Route));
|
||||||
CHECK_PTR(info);
|
CHECK_PTR(info);
|
||||||
info->path = (char*) path;
|
info->path = (char*) path;
|
||||||
info->path_len = path_len;
|
info->path_len = path_len;
|
||||||
|
@ -510,8 +510,8 @@ route * r3_route_createl(const char * path, int path_len) {
|
||||||
*
|
*
|
||||||
* method (int): METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_DELETE ...
|
* method (int): METHOD_GET, METHOD_POST, METHOD_PUT, METHOD_DELETE ...
|
||||||
*/
|
*/
|
||||||
route * r3_tree_insert_routel_ex(R3Node *tree, int method, const char *path, int path_len, void *data, char **errstr) {
|
R3Route * r3_tree_insert_routel_ex(R3Node *tree, int method, const char *path, int path_len, void *data, char **errstr) {
|
||||||
route *r = r3_route_createl(path, path_len);
|
R3Route *r = r3_route_createl(path, path_len);
|
||||||
CHECK_PTR(r);
|
CHECK_PTR(r);
|
||||||
r->request_method = method; // ALLOW GET OR POST METHOD
|
r->request_method = method; // ALLOW GET OR POST METHOD
|
||||||
R3Node * ret = r3_tree_insert_pathl_ex(tree, path, path_len, r, data, errstr);
|
R3Node * ret = r3_tree_insert_pathl_ex(tree, path, path_len, r, data, errstr);
|
||||||
|
@ -601,7 +601,7 @@ R3Edge * r3_node_find_common_prefix(R3Node *n, const char *path, int path_len, i
|
||||||
/**
|
/**
|
||||||
* Return the last inserted node.
|
* Return the last inserted node.
|
||||||
*/
|
*/
|
||||||
R3Node * r3_tree_insert_pathl_ex(R3Node *tree, const char *path, int path_len, route * route, void * data, char **errstr)
|
R3Node * r3_tree_insert_pathl_ex(R3Node *tree, const char *path, int path_len, R3Route * route, void * data, char **errstr)
|
||||||
{
|
{
|
||||||
R3Node * n = tree;
|
R3Node * n = tree;
|
||||||
|
|
||||||
|
@ -824,7 +824,7 @@ void r3_tree_dump(const R3Node * n, int level) {
|
||||||
*
|
*
|
||||||
* -1 == different route
|
* -1 == different route
|
||||||
*/
|
*/
|
||||||
inline int r3_route_cmp(const route *r1, const match_entry *r2) {
|
inline int r3_route_cmp(const R3Route *r1, const match_entry *r2) {
|
||||||
if (r1->request_method != 0) {
|
if (r1->request_method != 0) {
|
||||||
if (0 == (r1->request_method & r2->request_method) ) {
|
if (0 == (r1->request_method & r2->request_method) ) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -855,14 +855,14 @@ inline int r3_route_cmp(const route *r1, const match_entry *r2) {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void r3_node_append_route(R3Node * n, route * r) {
|
void r3_node_append_route(R3Node * n, R3Route * r) {
|
||||||
if (n->routes == NULL) {
|
if (n->routes == NULL) {
|
||||||
n->route_cap = 3;
|
n->route_cap = 3;
|
||||||
n->routes = zmalloc(sizeof(route) * n->route_cap);
|
n->routes = zmalloc(sizeof(R3Route) * n->route_cap);
|
||||||
}
|
}
|
||||||
if (n->route_len >= n->route_cap) {
|
if (n->route_len >= n->route_cap) {
|
||||||
n->route_cap *= 2;
|
n->route_cap *= 2;
|
||||||
n->routes = zrealloc(n->routes, sizeof(route) * n->route_cap);
|
n->routes = zrealloc(n->routes, sizeof(R3Route) * n->route_cap);
|
||||||
}
|
}
|
||||||
n->routes[ n->route_len++ ] = r;
|
n->routes[ n->route_len++ ] = r;
|
||||||
}
|
}
|
||||||
|
|
|
@ -608,7 +608,7 @@ END_TEST
|
||||||
|
|
||||||
START_TEST(test_route_cmp)
|
START_TEST(test_route_cmp)
|
||||||
{
|
{
|
||||||
route *r1 = r3_route_create("/blog/post");
|
R3Route *r1 = r3_route_create("/blog/post");
|
||||||
match_entry * m = match_entry_create("/blog/post");
|
match_entry * m = match_entry_create("/blog/post");
|
||||||
|
|
||||||
fail_if( r3_route_cmp(r1, m) == -1, "should match");
|
fail_if( r3_route_cmp(r1, m) == -1, "should match");
|
||||||
|
@ -732,7 +732,7 @@ START_TEST(test_insert_route)
|
||||||
r3_tree_insert_route(n, METHOD_POST, "/blog/post", &var2);
|
r3_tree_insert_route(n, METHOD_POST, "/blog/post", &var2);
|
||||||
|
|
||||||
match_entry * entry;
|
match_entry * entry;
|
||||||
route *r;
|
R3Route *r;
|
||||||
|
|
||||||
entry = match_entry_create("/blog/post");
|
entry = match_entry_create("/blog/post");
|
||||||
entry->request_method = METHOD_GET;
|
entry->request_method = METHOD_GET;
|
||||||
|
|
Loading…
Reference in a new issue