Add token list tests

This commit is contained in:
c9s 2014-05-15 12:47:14 +08:00
parent 767dba6e86
commit c91c06ec3b
5 changed files with 103 additions and 63 deletions

View file

@ -7,6 +7,5 @@
#ifndef STR_H #ifndef STR_H
#define STR_H #define STR_H
char** split_route_pattern(char *pattern, int pattern_len);
#endif /* !STR_H */ #endif /* !STR_H */

View file

@ -29,4 +29,8 @@ bool token_array_append(token_array * list, char * token);
void token_array_free(token_array *l); void token_array_free(token_array *l);
void token_array_dump(token_array *l);
token_array * split_route_pattern(char *pattern, int pattern_len);
#endif /* !TOKEN_H */ #endif /* !TOKEN_H */

View file

@ -9,66 +9,9 @@
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "str.h" #include "str.h"
#include "token.h"
/**
* This function is used to split route path into a string array, not for performance.
* hence this function should be safe.
*
* Split "/path/foo/{id}" into [ "/path" , "/foo" , "/{id}" ]
* Split "/path/bar/{id}" into [ "/path" , "/foo" , "/{id}" ]
* Split "/blog/post/{id}" into [ "/blog" , "/post" , "/{id}" ]
* Split "/blog/{id}" into [ "/blog" , "/{id}" ]
* Split "/blog" into [ "/blog" ]
* Split "/b" into [ "/b" ]
* Split "/{id}" into [ "/{id}" ]
*
* @param char* pattern
* @param int pattern_len
*
* @return char**
*/
char** split_route_pattern(char *pattern, int pattern_len) {
char *s1, *p = pattern;
char ** list;
unsigned int list_idx = 0;
unsigned int list_size = 20;
list = malloc( sizeof(char**) * list_size ); // default token list size
s1 = p;
while (*p && (p - pattern) < pattern_len ) {
// a slug
if ( *p == '{' ) {
while (*(p++) != '}') {
if ( p - pattern > pattern_len ) {
// XXX: unexpected error (unclosed slug)
}
}
list[list_idx] = strndup(s1, p-s1);
printf("%d -> %s\n", list_idx, list[list_idx]);
list_idx++;
s1 = p;
}
else if ( *p == '/' ) {
char *s2;
while (*(++p) != '/');
// printf("-> %s\n", strndup(s1, p-s1) );
list[list_idx] = strndup(s1, p-s1);
printf("%d -> %s\n", list_idx, list[list_idx]);
list_idx++;
s1 = p;
}
p++;
}
return NULL;
}
char** str_split(char* a_str, const char a_delim) char** str_split(char* a_str, const char a_delim)
{ {

View file

@ -5,6 +5,9 @@
* Distributed under terms of the MIT license. * Distributed under terms of the MIT license.
*/ */
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "token.h" #include "token.h"
@ -33,10 +36,21 @@ bool token_array_append(token_array * l, char * token) {
return FALSE; return FALSE;
} }
} }
l->tokens[ ++(l->len) ] = token; l->tokens[ l->len++ ] = token;
return TRUE; return TRUE;
} }
void token_array_dump(token_array *l) {
printf("[");
for ( int i = 0; i < l->len ; i++ ) {
printf("\"%s\"", l->tokens[i] );
if ( i + 1 != l->len ) {
printf(", ");
}
}
printf("]\n");
}
void token_array_free(token_array *l) { void token_array_free(token_array *l) {
for ( int i = 0; i < l->len ; i++ ) { for ( int i = 0; i < l->len ; i++ ) {
char * t = l->tokens[ i ]; char * t = l->tokens[ i ];
@ -46,3 +60,56 @@ void token_array_free(token_array *l) {
} }
/**
* This function is used to split route path into a string array, not for performance.
* hence this function should be safe.
*
* Split "/path/foo/{id}" into [ "/path" , "/foo" , "/{id}" ]
* Split "/path/bar/{id}" into [ "/path" , "/foo" , "/{id}" ]
* Split "/blog/post/{id}" into [ "/blog" , "/post" , "/{id}" ]
* Split "/blog/{id}" into [ "/blog" , "/{id}" ]
* Split "/blog" into [ "/blog" ]
* Split "/b" into [ "/b" ]
* Split "/{id}" into [ "/{id}" ]
*
* @param char* pattern
* @param int pattern_len
*
* @return char**
*/
token_array * split_route_pattern(char *pattern, int pattern_len) {
char *s1, *p = pattern;
token_array * token_array = token_array_create( 20 );
s1 = p;
p++;
while (*p && (p - pattern) < pattern_len ) {
// a slug
if ( *p == '{' ) {
// find closing '}'
while (*p != '}') {
p++;
assert(p - pattern < pattern_len ); // throw exception
}
p++; // contains the '}'
// printf("==> %s\n", strndup(s1, p-s1) );
token_array_append(token_array, strndup(s1, p-s1) );
s1 = p;
continue;
}
else if ( *p == '/' ) {
// printf("==> %s\n", strndup(s1, p-s1) );
token_array_append(token_array, strndup(s1, p-s1) );
s1 = p;
}
p++;
}
if ( p-s1 > 0 ) {
token_array_append(token_array, strndup(s1, p-s1) );
}
return token_array;
}

View file

@ -6,9 +6,36 @@
START_TEST (test_route) START_TEST (test_route)
{ {
split_route_pattern("/blog", strlen("/blog") ); token_array *t;
split_route_pattern("/foo/{id}", strlen("/foo/{id}") );
split_route_pattern("/{title}", strlen("/{title}") ); t = split_route_pattern("/blog", strlen("/blog") );
fail_if( t == NULL );
token_array_dump(t);
token_array_free(t);
t = split_route_pattern("/foo/{id}", strlen("/foo/{id}") );
fail_if( t == NULL );
token_array_dump(t);
fail_if( t->len != 2 );
token_array_free(t);
t = split_route_pattern("/foo/bar/{id}", strlen("/foo/bar/{id}") );
fail_if( t == NULL );
token_array_dump(t);
fail_if( t->len != 3 );
token_array_free(t);
t = split_route_pattern("/{title}", strlen("/{title}") );
fail_if( t == NULL );
token_array_dump(t);
fail_if( t->len != 1 );
token_array_free(t);
t = split_route_pattern("/", strlen("/") );
fail_if( t == NULL );
token_array_dump(t);
fail_if( t->len != 1 );
token_array_free(t);
} }
END_TEST END_TEST