Add token list struct
This commit is contained in:
parent
ff1800cd4a
commit
f8539fd950
9 changed files with 298 additions and 12 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,3 +6,4 @@ cmake_install.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
*.a
|
*.a
|
||||||
Testing
|
Testing
|
||||||
|
tags
|
||||||
|
|
13
HACKING.md
13
HACKING.md
|
@ -1,13 +1,22 @@
|
||||||
Related Articles
|
Related Articles
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
|
Judy Array
|
||||||
|
------------
|
||||||
|
|
||||||
- A 10-MINUTE DESCRIPTION OF HOW JUDY ARRAYS WORK AND WHY THEY ARE SO FAST <http://judy.sourceforge.net/doc/10minutes.htm>
|
- A 10-MINUTE DESCRIPTION OF HOW JUDY ARRAYS WORK AND WHY THEY ARE SO FAST <http://judy.sourceforge.net/doc/10minutes.htm>
|
||||||
- Hashtables vs Judy Arrays, Round 1 <http://rusty.ozlabs.org/?p=153>
|
- Hashtables vs Judy Arrays, Round 1 <http://rusty.ozlabs.org/?p=153>
|
||||||
- This Hash Table Is Faster Than a Judy Array <http://preshing.com/20130107/this-hash-table-is-faster-than-a-judy-array/>
|
- This Hash Table Is Faster Than a Judy Array <http://preshing.com/20130107/this-hash-table-is-faster-than-a-judy-array/>
|
||||||
- A Performance Comparison of Judy to Hash Tables <http://www.nothings.org/computer/judy/>
|
- A Performance Comparison of Judy to Hash Tables <http://www.nothings.org/computer/judy/>
|
||||||
- Faster (sometimes) Associative Arrays with Node.js <http://legitimatesounding.com/blog/Faster_sometimes_Associative_Arrays_with_Node_js.html>
|
- Faster (sometimes) Associative Arrays with Node.js <http://legitimatesounding.com/blog/Faster_sometimes_Associative_Arrays_with_Node_js.html>
|
||||||
|
|
||||||
|
Jemalloc
|
||||||
|
------------
|
||||||
|
https://github.com/jemalloc/jemalloc/wiki/Getting-Started
|
||||||
|
|
||||||
|
|
||||||
|
Prefix Tree / Radix Tree
|
||||||
|
-------------------------
|
||||||
|
- Radix Tree: <http://en.wikipedia.org/wiki/Radix_tree>
|
||||||
|
- Radix Tree in Linux Kernel: <http://blog.csdn.net/walkland/article/details/4006121>
|
||||||
|
- Radix Tree in Linux Kernel (source code): <https://github.com/torvalds/linux/blob/master/include/linux/radix-tree.h>
|
||||||
|
|
35
include/list.h
Normal file
35
include/list.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* list.h
|
||||||
|
* Copyright (C) 2014 c9s <c9s@c9smba.local>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
typedef struct _list_item {
|
||||||
|
void *value;
|
||||||
|
struct _list_item *prev;
|
||||||
|
struct _list_item *next;
|
||||||
|
} list_item;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int count;
|
||||||
|
list_item *head;
|
||||||
|
list_item *tail;
|
||||||
|
pthread_mutex_t mutex;
|
||||||
|
} list;
|
||||||
|
|
||||||
|
list *list_create();
|
||||||
|
void list_free(list *l);
|
||||||
|
|
||||||
|
list_item *list_add_element(list *l, void *ptr);
|
||||||
|
int list_remove_element(list *l, void *ptr);
|
||||||
|
void list_each_element(list *l, int (*func)(list_item *));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* !LIST_H */
|
32
include/token.h
Normal file
32
include/token.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* token.h
|
||||||
|
* Copyright (C) 2014 c9s <c9s@c9smba.local>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TOKEN_H
|
||||||
|
#define TOKEN_H
|
||||||
|
|
||||||
|
typedef unsigned char bool;
|
||||||
|
#define FALSE 0
|
||||||
|
#define TRUE 1
|
||||||
|
|
||||||
|
typedef struct _token_list {
|
||||||
|
char **tokens;
|
||||||
|
int len;
|
||||||
|
int cap;
|
||||||
|
} token_list;
|
||||||
|
|
||||||
|
token_list * token_list_create(int cap);
|
||||||
|
|
||||||
|
|
||||||
|
bool token_list_is_full(token_list * l);
|
||||||
|
|
||||||
|
bool token_list_resize(token_list *l, int new_cap);
|
||||||
|
|
||||||
|
bool token_list_append(token_list * list, char * token);
|
||||||
|
|
||||||
|
void token_list_free(token_list *l);
|
||||||
|
|
||||||
|
#endif /* !TOKEN_H */
|
|
@ -2,7 +2,7 @@
|
||||||
include_directories("${PROJECT_SOURCE_DIR}/include")
|
include_directories("${PROJECT_SOURCE_DIR}/include")
|
||||||
# install(TARGETS swiftnav-static DESTINATION lib${LIB_SUFFIX})
|
# install(TARGETS swiftnav-static DESTINATION lib${LIB_SUFFIX})
|
||||||
|
|
||||||
set(libr3_SRCS node.c str.c)
|
set(libr3_SRCS node.c str.c list.c token.c)
|
||||||
set(CMAKE_CFLAGS "-Wall -pipe -g3 -funroll-loops")
|
set(CMAKE_CFLAGS "-Wall -pipe -g3 -funroll-loops")
|
||||||
|
|
||||||
# add_library(r3-static STATIC ${libr3_SRCS})
|
# add_library(r3-static STATIC ${libr3_SRCS})
|
||||||
|
|
128
src/list.c
Normal file
128
src/list.c
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/*
|
||||||
|
* list.c
|
||||||
|
* Copyright (C) 2014 c9s <c9s@c9smba.local>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "list.h"
|
||||||
|
|
||||||
|
/* Naive linked list implementation */
|
||||||
|
|
||||||
|
list *
|
||||||
|
list_create()
|
||||||
|
{
|
||||||
|
list *l = (list *) malloc(sizeof(list));
|
||||||
|
l->count = 0;
|
||||||
|
l->head = NULL;
|
||||||
|
l->tail = NULL;
|
||||||
|
pthread_mutex_init(&(l->mutex), NULL);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
list_free(l)
|
||||||
|
list *l;
|
||||||
|
{
|
||||||
|
list_item *li, *tmp;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(l->mutex));
|
||||||
|
|
||||||
|
if (l != NULL) {
|
||||||
|
li = l->head;
|
||||||
|
while (li != NULL) {
|
||||||
|
tmp = li->next;
|
||||||
|
free(li);
|
||||||
|
li = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(l->mutex));
|
||||||
|
pthread_mutex_destroy(&(l->mutex));
|
||||||
|
free(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_item *
|
||||||
|
list_add_element(l, ptr)
|
||||||
|
list *l;
|
||||||
|
void *ptr;
|
||||||
|
{
|
||||||
|
list_item *li;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(l->mutex));
|
||||||
|
|
||||||
|
li = (list_item *) malloc(sizeof(list_item));
|
||||||
|
li->value = ptr;
|
||||||
|
li->next = NULL;
|
||||||
|
li->prev = l->tail;
|
||||||
|
|
||||||
|
if (l->tail == NULL) {
|
||||||
|
l->head = l->tail = li;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
l->tail = li;
|
||||||
|
}
|
||||||
|
l->count++;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(l->mutex));
|
||||||
|
|
||||||
|
return li;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
list_remove_element(l, ptr)
|
||||||
|
list *l;
|
||||||
|
void *ptr;
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
list_item *li = l->head;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(l->mutex));
|
||||||
|
|
||||||
|
while (li != NULL) {
|
||||||
|
if (li->value == ptr) {
|
||||||
|
if (li->prev == NULL) {
|
||||||
|
l->head = li->next;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
li->prev->next = li->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (li->next == NULL) {
|
||||||
|
l->tail = li->prev;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
li->next->prev = li->prev;
|
||||||
|
}
|
||||||
|
l->count--;
|
||||||
|
free(li);
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
li = li->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(l->mutex));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
list_each_element(l, func)
|
||||||
|
list *l;
|
||||||
|
int (*func)(list_item *);
|
||||||
|
{
|
||||||
|
list_item *li;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(l->mutex));
|
||||||
|
|
||||||
|
li = l->head;
|
||||||
|
while (li != NULL) {
|
||||||
|
if (func(li) == 1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
li = li->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(l->mutex));
|
||||||
|
}
|
34
src/str.c
34
src/str.c
|
@ -21,6 +21,7 @@
|
||||||
* Split "/blog/{id}" into [ "/blog" , "/{id}" ]
|
* Split "/blog/{id}" into [ "/blog" , "/{id}" ]
|
||||||
* Split "/blog" into [ "/blog" ]
|
* Split "/blog" into [ "/blog" ]
|
||||||
* Split "/b" into [ "/b" ]
|
* Split "/b" into [ "/b" ]
|
||||||
|
* Split "/{id}" into [ "/{id}" ]
|
||||||
*
|
*
|
||||||
* @param char* pattern
|
* @param char* pattern
|
||||||
* @param int pattern_len
|
* @param int pattern_len
|
||||||
|
@ -28,24 +29,43 @@
|
||||||
* @return char**
|
* @return char**
|
||||||
*/
|
*/
|
||||||
char** split_route_pattern(char *pattern, int pattern_len) {
|
char** split_route_pattern(char *pattern, int pattern_len) {
|
||||||
|
char *s1, *p = pattern;
|
||||||
|
|
||||||
char *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 ) {
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
// a slug
|
// a slug
|
||||||
if ( *p == '{' ) {
|
if ( *p == '{' ) {
|
||||||
char *s1 = p;
|
|
||||||
char *s2;
|
|
||||||
while (*(p++) != '}') {
|
while (*(p++) != '}') {
|
||||||
if ( p - pattern > pattern_len ) {
|
if ( p - pattern > pattern_len ) {
|
||||||
// XXX: unexpected error (unclosed slug)
|
// XXX: unexpected error (unclosed slug)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s2 = p;
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
49
src/token.c
Normal file
49
src/token.c
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* token.c
|
||||||
|
* Copyright (C) 2014 c9s <c9s@c9smba.local>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
|
|
||||||
|
token_list * token_list_create(int cap) {
|
||||||
|
token_list * list = (token_list*) malloc( sizeof(token_list) );
|
||||||
|
list->len = 0;
|
||||||
|
list->cap = cap;
|
||||||
|
list->tokens = (char**) malloc( sizeof(char*) * cap);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool token_list_is_full(token_list * l) {
|
||||||
|
return l->len >= l->cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool token_list_resize(token_list *l, int new_cap) {
|
||||||
|
l->tokens = realloc(l->tokens, sizeof(char**) * new_cap);
|
||||||
|
l->cap = new_cap;
|
||||||
|
return l->tokens != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool token_list_append(token_list * l, char * token) {
|
||||||
|
if ( token_list_is_full(l) ) {
|
||||||
|
bool ret = token_list_resize(l, l->cap + 20);
|
||||||
|
if (ret == FALSE ) {
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l->tokens[ ++(l->len) ] = token;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void token_list_free(token_list *l) {
|
||||||
|
for ( int i = 0; i < l->len ; i++ ) {
|
||||||
|
char * t = l->tokens[ i ];
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
free(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,28 @@
|
||||||
#include <check.h>
|
#include <check.h>
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
|
#include "token.h"
|
||||||
|
|
||||||
START_TEST (test_route)
|
START_TEST (test_route)
|
||||||
{
|
{
|
||||||
|
split_route_pattern("/blog", strlen("/blog") );
|
||||||
|
split_route_pattern("/foo/{id}", strlen("/foo/{id}") );
|
||||||
|
split_route_pattern("/{title}", strlen("/{title}") );
|
||||||
|
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
START_TEST (test_route2)
|
START_TEST (test_token_list)
|
||||||
{
|
{
|
||||||
|
token_list * l = token_list_create(10);
|
||||||
|
fail_if( l == NULL );
|
||||||
|
fail_if( FALSE == token_list_resize(l, l->cap * 2) );
|
||||||
|
|
||||||
|
fail_if( FALSE == token_list_append(l, strdup("abc") ) );
|
||||||
|
fail_if( FALSE == token_list_append(l, strdup("foo") ) );
|
||||||
|
fail_if( FALSE == token_list_append(l, strdup("bar") ) );
|
||||||
|
|
||||||
|
token_list_free(l);
|
||||||
}
|
}
|
||||||
END_TEST
|
END_TEST
|
||||||
|
|
||||||
|
@ -20,7 +32,7 @@ Suite* r3_suite (void) {
|
||||||
|
|
||||||
TCase *tcase = tcase_create("testcase");
|
TCase *tcase = tcase_create("testcase");
|
||||||
tcase_add_test(tcase, test_route);
|
tcase_add_test(tcase, test_route);
|
||||||
tcase_add_test(tcase, test_route2);
|
tcase_add_test(tcase, test_token_list);
|
||||||
|
|
||||||
suite_add_tcase(suite, tcase);
|
suite_add_tcase(suite, tcase);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue