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
|
||||
*.a
|
||||
Testing
|
||||
tags
|
||||
|
|
13
HACKING.md
13
HACKING.md
|
@ -1,13 +1,22 @@
|
|||
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>
|
||||
- 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/>
|
||||
- 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>
|
||||
|
||||
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")
|
||||
# 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")
|
||||
|
||||
# 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" into [ "/blog" ]
|
||||
* Split "/b" into [ "/b" ]
|
||||
* Split "/{id}" into [ "/{id}" ]
|
||||
*
|
||||
* @param char* pattern
|
||||
* @param int pattern_len
|
||||
|
@ -28,24 +29,43 @@
|
|||
* @return char**
|
||||
*/
|
||||
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
|
||||
if ( *p == '{' ) {
|
||||
char *s1 = p;
|
||||
char *s2;
|
||||
while (*(p++) != '}') {
|
||||
if ( p - pattern > pattern_len ) {
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
|
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 "str.h"
|
||||
#include "node.h"
|
||||
#include "token.h"
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
|
@ -20,7 +32,7 @@ Suite* r3_suite (void) {
|
|||
|
||||
TCase *tcase = tcase_create("testcase");
|
||||
tcase_add_test(tcase, test_route);
|
||||
tcase_add_test(tcase, test_route2);
|
||||
tcase_add_test(tcase, test_token_list);
|
||||
|
||||
suite_add_tcase(suite, tcase);
|
||||
|
||||
|
|
Loading…
Reference in a new issue