diff --git a/include/r3_str.h b/include/r3_str.h index e07eb21..1504486 100644 --- a/include/r3_str.h +++ b/include/r3_str.h @@ -10,7 +10,7 @@ #include "r3.h" #include "config.h" -int slug_count(const char * p, int len); +int slug_count(const char * p, int len, char ** errstr); char * slug_compile(const char * str, int len); @@ -20,7 +20,7 @@ char * slug_find_pattern(const char *s1, int *len); char * slug_find_placeholder(const char *s1, int *len); -char * inside_slug(const char * needle, int needle_len, char *offset); +char * inside_slug(const char * needle, int needle_len, char *offset, char **errstr); char * ltrim_slash(char* str); diff --git a/src/node.c b/src/node.c index 2500aee..08cba95 100644 --- a/src/node.c +++ b/src/node.c @@ -493,7 +493,7 @@ node * r3_tree_insert_pathl_(node *tree, const char *path, int path_len, route * // branch the edge at correct position (avoid broken slugs) const char *slug_s; - if ( (slug_s = inside_slug(path, path_len, (char*) path + prefix_len)) != NULL ) { + if ( (slug_s = inside_slug(path, path_len, ((char*) path + prefix_len), NULL)) != NULL ) { prefix_len = slug_s - path; } @@ -503,7 +503,9 @@ node * r3_tree_insert_pathl_(node *tree, const char *path, int path_len, route * // common prefix not found, insert a new edge for this pattern if ( prefix_len == 0 ) { // there are two more slugs, we should break them into several parts - int slug_cnt = slug_count(path, path_len); + char *errstr = NULL; + int slug_cnt = slug_count(path, path_len, &errstr); + if ( slug_cnt > 1 ) { int slug_len; char *p = slug_find_placeholder(path, &slug_len); diff --git a/src/str.c b/src/str.c index cdfdf57..c2e7721 100644 --- a/src/str.c +++ b/src/str.c @@ -42,7 +42,7 @@ int r3_pattern_to_opcode(const char * pattern, int len) { /** * provide a quick way to count slugs, simply search for '{' */ -int slug_count(const char * p, int len) { +int slug_count(const char * p, int len, char **errstr) { int s = 0; int lev = 0; while( len-- ) { @@ -56,6 +56,15 @@ int slug_count(const char * p, int len) { } p++; } + /* + XXX: + if (lev != 0) { + if (errstr) { + asprintf(errstr, "incomplete slug pattern: %s", p); + } + return 0; + } + */ return s; } @@ -63,7 +72,7 @@ bool contains_slug(const char * str) { return strchr(str, '{') != NULL ? TRUE : FALSE; } -char * inside_slug(const char * needle, int needle_len, char *offset) { +char * inside_slug(const char * needle, int needle_len, char *offset, char **errstr) { char * s1 = offset; char * s2 = offset; @@ -89,6 +98,13 @@ char * inside_slug(const char * needle, int needle_len, char *offset) { if (found_s1 && found_s2) { return s1; } + if (found_s1 || found_s2) { + // wrong slug pattern + if(errstr) { + asprintf(errstr, "incomplete slug pattern"); + } + return NULL; + } return NULL; } diff --git a/tests/check_slug.c b/tests/check_slug.c index 5fc362a..ca42f85 100644 --- a/tests/check_slug.c +++ b/tests/check_slug.c @@ -76,19 +76,19 @@ START_TEST (test_inside_slug) { char * pattern = "/user/{name:\\s+}/to/{id}"; char * offset = strchr(pattern, '{') + 2; - ck_assert( (int)inside_slug(pattern, strlen(pattern), offset) ); - ck_assert( *(inside_slug(pattern, strlen(pattern), offset)) == '{' ); - ck_assert( ! inside_slug(pattern, strlen(pattern), pattern) ); + ck_assert( (int)inside_slug(pattern, strlen(pattern), offset, NULL) ); + ck_assert( *(inside_slug(pattern, strlen(pattern), offset, NULL)) == '{' ); + ck_assert( ! inside_slug(pattern, strlen(pattern), pattern, NULL) ); } END_TEST START_TEST (test_slug_count) { char * pattern = "/user/{name:\\s+}/to/{id}"; - ck_assert_int_eq( slug_count(pattern, strlen(pattern) ), 2 ); + ck_assert_int_eq( slug_count(pattern, strlen(pattern), NULL), 2 ); char * pattern2 = "/user/{name:\\d{3}}/to/{id}"; - ck_assert_int_eq( slug_count(pattern2, strlen(pattern) ), 2 ); + ck_assert_int_eq( slug_count(pattern2, strlen(pattern), NULL), 2 ); } END_TEST