11 changed files with 0 additions and 1639 deletions
-
23include/cbufpool.h
-
303src/binarytree.c
-
10src/cbufpool.c
-
42src/configtest.c
-
54src/hash.c
-
55src/mmapfiletest.c
-
54src/mmapfiletest2.c
-
797src/rbtree.c
-
176src/rbtree2.c
-
107src/usertest.c
-
18src/uuid.c
@ -1,23 +0,0 @@ |
|||||
/** |
|
||||
* As the initializations of cbufs is complicated and time consuming |
|
||||
* with all this shared memory initialization stuff and each cbuf |
|
||||
* always is the same (at least for this application) we don't free |
|
||||
* them after they are not used anymore. |
|
||||
* Instead we store the in this pool and reuse then the next time |
|
||||
* they are needed. |
|
||||
* |
|
||||
* Well thats the idea of this. |
|
||||
* |
|
||||
* OK, after review the code...it has been some time since I wrote it, |
|
||||
* I realize that only one cbuf is used right now. |
|
||||
* Each connection holds their unprocessed data in another heap reagion |
|
||||
* and reinitializes the ringbuffer each time with this. |
|
||||
* |
|
||||
* This seems both inefficient and error prone. So I will change this. |
|
||||
* The only question is, how large should our circular buffer be and |
|
||||
* how many connections do we expect in paralell... |
|
||||
* |
|
||||
* We need to have some handling to not accept any more connection |
|
||||
* when we reached the maximum amount for cbuffers and none is left in |
|
||||
* the pool. |
|
||||
*/ |
|
||||
@ -1,303 +0,0 @@ |
|||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
|
|
||||
|
|
||||
struct element |
|
||||
{ |
|
||||
int data; |
|
||||
|
|
||||
struct element * parent; |
|
||||
struct element * left; |
|
||||
struct element * right; |
|
||||
}; |
|
||||
|
|
||||
struct element * |
|
||||
newElement(int data) |
|
||||
{ |
|
||||
struct element * el = malloc(sizeof(struct element)); |
|
||||
el->data = data; |
|
||||
el->parent = NULL; |
|
||||
el->left = NULL; |
|
||||
el->right = NULL; |
|
||||
|
|
||||
return el; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* find element in tree |
|
||||
*/ |
|
||||
struct element * |
|
||||
findElement(struct element * tree, int data) |
|
||||
{ |
|
||||
while (NULL != tree) { |
|
||||
if (tree->data == data) { |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
if (data < tree->data) { |
|
||||
tree = tree->left; |
|
||||
} else { |
|
||||
tree = tree->right; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return tree; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* insert element in tree |
|
||||
*/ |
|
||||
void |
|
||||
insertElement(struct element ** tree, int data) |
|
||||
{ |
|
||||
struct element * node = *tree; |
|
||||
|
|
||||
if (NULL == node) { |
|
||||
*tree = newElement(data); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
while (data != node->data) { |
|
||||
if (data < node->data) { |
|
||||
if (NULL == node->left) { |
|
||||
node->left = newElement(data); |
|
||||
node->left->parent = node; |
|
||||
return; |
|
||||
} else { |
|
||||
node = node->left; |
|
||||
} |
|
||||
} else { |
|
||||
if (NULL == node->right) { |
|
||||
node->right = newElement(data); |
|
||||
node->right->parent = node; |
|
||||
return; |
|
||||
} else { |
|
||||
node = node->right; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* delete element from tree |
|
||||
* here multiple functions are involved.... |
|
||||
* ======================================================================= |
|
||||
*/ |
|
||||
/** |
|
||||
* find minimum of the right subtree aka leftmost leaf of right subtree |
|
||||
* aka left in-order successor. |
|
||||
* We return the parent of the element in the out argument parent. |
|
||||
* This can be NULL wenn calling. |
|
||||
*/ |
|
||||
struct element * |
|
||||
findInOrderSuccessor(struct element * tree) |
|
||||
{ |
|
||||
struct element * node = tree->right; |
|
||||
|
|
||||
while (NULL != node->left) { |
|
||||
node = node->left; |
|
||||
} |
|
||||
|
|
||||
return node; |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
deleteElement(struct element ** tree, int data) |
|
||||
{ |
|
||||
struct element * node = *tree; |
|
||||
|
|
||||
// find the relevant node and it's parent |
|
||||
while (NULL != node && node->data != data) { |
|
||||
if (data < node->data) { |
|
||||
node = node->left; |
|
||||
} else { |
|
||||
node = node->right; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// element not found |
|
||||
if (NULL == node) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// distinuish 3 cases, where the resolving of each case leads to the |
|
||||
// precondition of the other. |
|
||||
|
|
||||
// case 1: two children |
|
||||
if (NULL != node->left && NULL != node->right) { |
|
||||
struct element * successor = findInOrderSuccessor(node); |
|
||||
|
|
||||
node->data = successor->data; |
|
||||
node = successor; |
|
||||
} |
|
||||
|
|
||||
// case 2: one child wither left or right |
|
||||
if (NULL != node->left) { |
|
||||
//node->data = node->left->data; |
|
||||
//node = node->left; |
|
||||
if (NULL != node->parent) { |
|
||||
if (node == node->parent->left) { |
|
||||
node->parent->left = node->left; |
|
||||
} else { |
|
||||
node->parent->right = node->left; |
|
||||
} |
|
||||
} |
|
||||
node->left->parent = node->parent; |
|
||||
} |
|
||||
|
|
||||
if (NULL != node->right) { |
|
||||
//node->data = node->right->data; |
|
||||
//node = node->right; |
|
||||
if (NULL != node->parent) { |
|
||||
if (node == node->parent->left) { |
|
||||
node->parent->left = node->right; |
|
||||
} else { |
|
||||
node->parent->right = node->right; |
|
||||
} |
|
||||
} |
|
||||
node->right->parent = node->parent; |
|
||||
} |
|
||||
|
|
||||
// case 3: we are a leaf |
|
||||
if (NULL != node->parent) { |
|
||||
if (node == node->parent->left) { |
|
||||
node->parent->left = NULL; |
|
||||
} else { |
|
||||
node->parent->right = NULL; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (node == *tree) { |
|
||||
if (NULL != node->left) { |
|
||||
*tree = node->left; |
|
||||
} else if (NULL != node->right) { |
|
||||
*tree = node->right; |
|
||||
} else { |
|
||||
*tree = NULL; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
free(node); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void |
|
||||
traverse(struct element * tree, void (*cb)(int, int)) |
|
||||
{ |
|
||||
struct element * previous = tree; |
|
||||
struct element * node = tree; |
|
||||
int depth = 1; |
|
||||
|
|
||||
/* |
|
||||
* I think this has something like O(n+log(n)) on a ballanced |
|
||||
* tree because I have to traverse back the rightmost leaf to |
|
||||
* the root to get a break condition. |
|
||||
*/ |
|
||||
while (node) { |
|
||||
/* |
|
||||
* If we come from the right so nothing and go to our |
|
||||
* next parent. |
|
||||
*/ |
|
||||
if (previous == node->right) { |
|
||||
previous = node; |
|
||||
node = node->parent; |
|
||||
depth--; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if ((NULL == node->left || previous == node->left)) { |
|
||||
/* |
|
||||
* If there are no more elements to the left or we |
|
||||
* came from the left, process data. |
|
||||
*/ |
|
||||
cb(node->data, depth); |
|
||||
previous = node; |
|
||||
|
|
||||
if (NULL != node->right) { |
|
||||
node = node->right; |
|
||||
depth++; |
|
||||
} else { |
|
||||
node = node->parent; |
|
||||
depth--; |
|
||||
} |
|
||||
} else { |
|
||||
/* |
|
||||
* if there are more elements to the left go there. |
|
||||
*/ |
|
||||
previous = node; |
|
||||
node = node->left; |
|
||||
depth++; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void printElement(int data, int depth) |
|
||||
{ |
|
||||
int i; |
|
||||
|
|
||||
printf("%02d(%02d)", data, depth); |
|
||||
for (i=0; i<depth; i++) printf("-"); |
|
||||
puts(""); |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* ======================================================================= |
|
||||
*/ |
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
struct element * root = NULL; |
|
||||
|
|
||||
insertElement(&root, 13); |
|
||||
insertElement(&root, 8); |
|
||||
insertElement(&root, 16); |
|
||||
insertElement(&root, 11); |
|
||||
insertElement(&root, 3); |
|
||||
insertElement(&root, 9); |
|
||||
insertElement(&root, 12); |
|
||||
insertElement(&root, 10); |
|
||||
|
|
||||
/* |
|
||||
* delete does not work correctly here.. |
|
||||
* luckily I do not need the simple binary trees anymore |
|
||||
* as I have rbtrees. |
|
||||
*/ |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 8); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 11); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 13); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 3); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 16); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 10); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 9); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
deleteElement(&root, 12); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,10 +0,0 @@ |
|||||
/** |
|
||||
* As the initializations of cbufs is complicated and time consuming |
|
||||
* with all this shared memory initialization stuff and each cbuf |
|
||||
* always is the same (at least for this application) we don't free |
|
||||
* them after they are not used anymore. |
|
||||
* Instead we store the in this pool and reuse then the next time |
|
||||
* they are needed. |
|
||||
* |
|
||||
* Well thats the idea of this. |
|
||||
*/ |
|
||||
@ -1,42 +0,0 @@ |
|||||
#include <stdio.h> |
|
||||
|
|
||||
#include "class.h" |
|
||||
#include "commons.h" |
|
||||
#include "config/config.h" |
|
||||
#include "config/value.h" |
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
Config config = new(Config, "./testconfig.cfg"); |
|
||||
ConfigValue val; |
|
||||
|
|
||||
val = configGet(config, CSTRA("dummy")); |
|
||||
|
|
||||
if (NULL != val) { |
|
||||
switch (val->type) { |
|
||||
case CONFIG_VALUE_STRING: |
|
||||
printf( |
|
||||
"Value for dummy: (STRING): %s\n", |
|
||||
(val->value).string); |
|
||||
break; |
|
||||
|
|
||||
case CONFIG_VALUE_NUMERIC: |
|
||||
printf( |
|
||||
"Value for dummy: (NUMERIC): %lld\n", |
|
||||
(val->value).number); |
|
||||
break; |
|
||||
|
|
||||
default: |
|
||||
printf("Invalid config...that should never happen\n"); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
delete(config); |
|
||||
memCleanup(); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,54 +0,0 @@ |
|||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
|
|
||||
#include "class.h" |
|
||||
#include "commons.h" |
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
#include "hash.h" |
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
|
|
||||
/** |
|
||||
* ======================================================================= |
|
||||
*/ |
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
Hash hash = new(Hash); |
|
||||
HashValue deleted; |
|
||||
|
|
||||
hashAdd(hash, new(HashValue, CSTRA("foo"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("hjkfdd"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("j8frheff"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("f9e0g"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("gfrk9e0"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("fr09ie"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("fu8de9"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("rehw78"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("fcrne9"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("new8"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("fdhe78"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("dhew8"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("jfde9w8"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("dhe7w89"), CSTRA("bar"))); |
|
||||
hashAdd(hash, new(HashValue, CSTRA("fduew89"), CSTRA("bar"))); |
|
||||
|
|
||||
deleted = hashDelete(hash, CSTRA("f9e0g")); |
|
||||
delete(deleted); |
|
||||
deleted = hashDelete(hash, CSTRA("fcrne9")); |
|
||||
delete(deleted); |
|
||||
deleted = hashDelete(hash, CSTRA("fr09ie")); |
|
||||
delete(deleted); |
|
||||
deleted = hashDelete(hash, CSTRA("jfde9w8")); |
|
||||
delete(deleted); |
|
||||
deleted = hashDelete(hash, CSTRA("j8frheff")); |
|
||||
delete(deleted); |
|
||||
|
|
||||
delete(hash); |
|
||||
memCleanup(); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,55 +0,0 @@ |
|||||
// for mmap |
|
||||
#include <sys/mman.h> |
|
||||
|
|
||||
// for random |
|
||||
#include <stdlib.h> |
|
||||
|
|
||||
// for open and fstat |
|
||||
#include <sys/types.h> |
|
||||
#include <sys/stat.h> |
|
||||
#include <fcntl.h> |
|
||||
|
|
||||
// for puts |
|
||||
#include <stdio.h> |
|
||||
|
|
||||
// for time |
|
||||
#include <time.h> |
|
||||
|
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
struct stat st; |
|
||||
char * map; |
|
||||
size_t position; |
|
||||
char print_buf[101]; |
|
||||
int i; |
|
||||
|
|
||||
print_buf[100] = '\0'; |
|
||||
|
|
||||
int fd = open("./mmapfiletest.c", O_RDONLY); |
|
||||
|
|
||||
fstat(fd, &st); |
|
||||
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); |
|
||||
|
|
||||
srandom(time(NULL)); |
|
||||
position = random() % (st.st_size - 100); |
|
||||
|
|
||||
for (i=0; i<100; i+=10) { |
|
||||
print_buf[i+0] = map[position + i + 0]; |
|
||||
print_buf[i+1] = map[position + i + 1]; |
|
||||
print_buf[i+2] = map[position + i + 2]; |
|
||||
print_buf[i+3] = map[position + i + 3]; |
|
||||
print_buf[i+4] = map[position + i + 4]; |
|
||||
print_buf[i+5] = map[position + i + 5]; |
|
||||
print_buf[i+6] = map[position + i + 6]; |
|
||||
print_buf[i+7] = map[position + i + 7]; |
|
||||
print_buf[i+8] = map[position + i + 8]; |
|
||||
print_buf[i+9] = map[position + i + 9]; |
|
||||
} |
|
||||
|
|
||||
puts(print_buf); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,54 +0,0 @@ |
|||||
// for random |
|
||||
#include <stdlib.h> |
|
||||
|
|
||||
// for puts |
|
||||
#include <stdio.h> |
|
||||
|
|
||||
// for time |
|
||||
#include <time.h> |
|
||||
|
|
||||
#include "class.h" |
|
||||
#include "commons.h" |
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
#include "asset.h" |
|
||||
|
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
size_t i; |
|
||||
size_t position; |
|
||||
char print_buf[101]; |
|
||||
|
|
||||
Asset asset = new(Asset, CSTRA("./src/mmapfiletest.c")); |
|
||||
|
|
||||
print_buf[100] = '\0'; |
|
||||
|
|
||||
srandom(time(NULL)); |
|
||||
position = random() % (asset->size - 100); |
|
||||
|
|
||||
for (i=0; i<100; i+=10) { |
|
||||
print_buf[i+0] = asset->data[position+i+0]; |
|
||||
print_buf[i+1] = asset->data[position+i+1]; |
|
||||
print_buf[i+2] = asset->data[position+i+2]; |
|
||||
print_buf[i+3] = asset->data[position+i+3]; |
|
||||
print_buf[i+4] = asset->data[position+i+4]; |
|
||||
print_buf[i+5] = asset->data[position+i+5]; |
|
||||
print_buf[i+6] = asset->data[position+i+6]; |
|
||||
print_buf[i+7] = asset->data[position+i+7]; |
|
||||
print_buf[i+8] = asset->data[position+i+8]; |
|
||||
print_buf[i+9] = asset->data[position+i+9]; |
|
||||
} |
|
||||
|
|
||||
if (NULL != asset->mime_type) { |
|
||||
puts(asset->mime_type); |
|
||||
} |
|
||||
puts(print_buf); |
|
||||
|
|
||||
delete(asset); |
|
||||
memCleanup(); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,797 +0,0 @@ |
|||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#define NVALUES 10 |
|
||||
|
|
||||
enum rbColor {rbBlack=1, rbRed=2}; |
|
||||
|
|
||||
|
|
||||
struct element |
|
||||
{ |
|
||||
size_t size; |
|
||||
void * ptr; |
|
||||
|
|
||||
enum rbColor color; |
|
||||
|
|
||||
struct element * next; |
|
||||
struct element * last; |
|
||||
|
|
||||
struct element * parent; |
|
||||
struct element * left; |
|
||||
struct element * right; |
|
||||
}; |
|
||||
|
|
||||
struct element * |
|
||||
newElement(size_t size) |
|
||||
{ |
|
||||
struct element * element = malloc(size + sizeof(struct element)); |
|
||||
|
|
||||
element->size = size; |
|
||||
element->ptr = element + sizeof(struct element); |
|
||||
|
|
||||
element->next = NULL; |
|
||||
element->last = NULL; |
|
||||
|
|
||||
element->color = rbRed; |
|
||||
element->parent = NULL; |
|
||||
element->left = NULL; |
|
||||
element->right = NULL; |
|
||||
|
|
||||
return element; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* find element in tree |
|
||||
*/ |
|
||||
struct element * |
|
||||
findElement(struct element * tree, size_t size) |
|
||||
{ |
|
||||
struct element * fitting = NULL; |
|
||||
|
|
||||
while (NULL != tree) { |
|
||||
if (tree->size == size) { |
|
||||
fitting = tree; |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
if (size > tree->size) { |
|
||||
tree = tree->right; |
|
||||
} else { |
|
||||
fitting = tree; |
|
||||
tree = tree->left; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return fitting; |
|
||||
} |
|
||||
|
|
||||
/* |
|
||||
* function to get specific elements needed for |
|
||||
* rb handling, grandparent, uncle and sibbling |
|
||||
*/ |
|
||||
struct element * |
|
||||
grandparent(struct element * node) |
|
||||
{ |
|
||||
if (NULL != node && NULL != node->parent) { |
|
||||
return node->parent->parent; |
|
||||
} |
|
||||
|
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
struct element * |
|
||||
uncle(struct element * node) |
|
||||
{ |
|
||||
struct element * gp = grandparent(node); |
|
||||
|
|
||||
if (NULL == gp) { |
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
if (node->parent == gp->left) { |
|
||||
return gp->right; |
|
||||
} |
|
||||
|
|
||||
return gp->left; |
|
||||
} |
|
||||
|
|
||||
struct element * |
|
||||
sibling(struct element * node) |
|
||||
{ |
|
||||
if (NULL == node) { |
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
if (NULL == node->parent->left || node == node->parent->left) { |
|
||||
return node->parent->right; |
|
||||
} else { |
|
||||
return node->parent->left; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/* |
|
||||
* tree modifications...needed for rb handling. |
|
||||
*/ |
|
||||
void |
|
||||
rotateLeft(struct element ** tree, struct element * node) |
|
||||
{ |
|
||||
struct element * rightChild = node->right; |
|
||||
struct element * rcLeftSub = node->right->left; |
|
||||
|
|
||||
rightChild->left = node; |
|
||||
rightChild->parent = node->parent; |
|
||||
node->right = rcLeftSub; |
|
||||
if (NULL != rcLeftSub) { |
|
||||
rcLeftSub->parent = node; |
|
||||
} |
|
||||
|
|
||||
if (node->parent) { |
|
||||
if (node->parent->left == node) { |
|
||||
node->parent->left = rightChild; |
|
||||
} else { |
|
||||
node->parent->right = rightChild; |
|
||||
} |
|
||||
} else { |
|
||||
*tree = rightChild; |
|
||||
} |
|
||||
|
|
||||
node->parent = rightChild; |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
rotateRight(struct element ** tree, struct element * node) |
|
||||
{ |
|
||||
struct element * leftChild = node->left; |
|
||||
struct element * lcRightSub = node->left->right; |
|
||||
|
|
||||
leftChild->right = node; |
|
||||
leftChild->parent = node->parent; |
|
||||
node->left = lcRightSub; |
|
||||
if (NULL != lcRightSub) { |
|
||||
lcRightSub->parent = node; |
|
||||
} |
|
||||
|
|
||||
if (node->parent) { |
|
||||
if (node->parent->left == node) { |
|
||||
node->parent->left = leftChild; |
|
||||
} else { |
|
||||
node->parent->right = leftChild; |
|
||||
} |
|
||||
} else { |
|
||||
*tree = leftChild; |
|
||||
} |
|
||||
|
|
||||
node->parent = leftChild; |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
replaceNode( |
|
||||
struct element ** tree, |
|
||||
struct element * node1, |
|
||||
struct element * node2) |
|
||||
{ |
|
||||
if (NULL != node1->parent) { |
|
||||
if (node1 == node1->parent->left) { |
|
||||
node1->parent->left = node2; |
|
||||
} else { |
|
||||
node1->parent->right = node2; |
|
||||
} |
|
||||
} else { |
|
||||
*tree = node2; |
|
||||
} |
|
||||
|
|
||||
if (NULL != node2) { |
|
||||
node2->parent = node1->parent; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
/** |
|
||||
* insert element in tree |
|
||||
*/ |
|
||||
struct element * |
|
||||
insertElement(struct element ** tree, struct element * element) |
|
||||
{ |
|
||||
struct element * node = *tree; |
|
||||
struct element * new_node = NULL; |
|
||||
struct element * u; |
|
||||
struct element * g; |
|
||||
|
|
||||
element->next = NULL; |
|
||||
element->last = NULL; |
|
||||
|
|
||||
element->color = rbRed; |
|
||||
element->parent = NULL; |
|
||||
element->left = NULL; |
|
||||
element->right = NULL; |
|
||||
|
|
||||
// if tree is empty it's simple... :) |
|
||||
if (NULL == node) { |
|
||||
*tree = node = new_node = element; |
|
||||
} else { |
|
||||
// normal binary tree add.... |
|
||||
while (NULL != node) { |
|
||||
if (element->size < node->size) { |
|
||||
if (NULL == node->left) { |
|
||||
node->left = element; |
|
||||
node->left->parent = node; |
|
||||
new_node = node = node->left; |
|
||||
break; |
|
||||
} else { |
|
||||
node = node->left; |
|
||||
} |
|
||||
} else if (element->size > node->size) { |
|
||||
if (NULL == node->right) { |
|
||||
node->right = element; |
|
||||
node->right->parent = node; |
|
||||
new_node = node = node->right; |
|
||||
break; |
|
||||
} else { |
|
||||
node = node->right; |
|
||||
} |
|
||||
} else { |
|
||||
if (NULL == node->next) { |
|
||||
node->next = element; |
|
||||
node->last = element; |
|
||||
} else { |
|
||||
node->last->next = element; |
|
||||
node->last = element; |
|
||||
} |
|
||||
return node; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (NULL != new_node) { |
|
||||
/* |
|
||||
* handle reballancing rb style |
|
||||
*/ |
|
||||
while (1) { |
|
||||
// case 1 |
|
||||
if (node->parent == NULL) { |
|
||||
node->color = rbBlack; |
|
||||
// we're done.... :) |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
// case 2 |
|
||||
if (node->parent->color == rbBlack) { |
|
||||
// Tree is still valid ... wow, again we're done... :) |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
// case 3 |
|
||||
u = uncle(node); |
|
||||
g = grandparent(node); |
|
||||
|
|
||||
if (u != NULL && u->color == rbRed) { |
|
||||
node->parent->color = rbBlack; |
|
||||
u->color = rbBlack; |
|
||||
g->color = rbRed; |
|
||||
|
|
||||
node = g; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
// case 4 |
|
||||
if (node == node->parent->right && node->parent == g->left) { |
|
||||
rotateLeft(tree, node->parent); |
|
||||
node = node->left; |
|
||||
} else if (node == node->parent->left && node->parent == g->right) { |
|
||||
|
|
||||
rotateRight(tree, node->parent); |
|
||||
node = node->right; |
|
||||
} |
|
||||
|
|
||||
// case 5 |
|
||||
g = grandparent(node); |
|
||||
|
|
||||
node->parent->color = rbBlack; |
|
||||
g->color = rbRed; |
|
||||
|
|
||||
if (node == node->parent->left) { |
|
||||
rotateRight(tree, g); |
|
||||
} else { |
|
||||
rotateLeft(tree, g); |
|
||||
} |
|
||||
|
|
||||
// we're done.. |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return new_node; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* delete element from tree |
|
||||
* here multiple functions are involved.... |
|
||||
* ======================================================================= |
|
||||
*/ |
|
||||
/** |
|
||||
* find minimum of the right subtree aka leftmost leaf of right subtree |
|
||||
* aka left in-order successor. |
|
||||
* We return the parent of the element in the out argument parent. |
|
||||
* This can be NULL wenn calling. |
|
||||
* |
|
||||
* 2: *successor = {size = 80, ptr = 0x603ae0, color = rbRed, parent = 0x603160, |
|
||||
* left = 0x0, right = 0x0} |
|
||||
* 1: *node = {size = 70, ptr = 0x603a60, color = rbBlack, parent = 0x603070, |
|
||||
* left = 0x6030e0, right = 0x6031e0} |
|
||||
* |
|
||||
*/ |
|
||||
struct element * |
|
||||
findInOrderSuccessor(struct element * tree) |
|
||||
{ |
|
||||
struct element * node = tree->right; |
|
||||
|
|
||||
while (NULL != node->left) { |
|
||||
node = node->left; |
|
||||
} |
|
||||
|
|
||||
return node; |
|
||||
} |
|
||||
|
|
||||
struct element * deleteOneChild(struct element **, struct element *); |
|
||||
|
|
||||
struct element * |
|
||||
deleteElement(struct element ** tree, struct element * element) |
|
||||
{ |
|
||||
struct element * node = *tree; |
|
||||
struct element * del_node; |
|
||||
struct element * child; |
|
||||
struct element * s; |
|
||||
|
|
||||
// find the relevant node and it's parent |
|
||||
while (NULL != node) { |
|
||||
|
|
||||
if (element->size < node->size) { |
|
||||
node = node->left; |
|
||||
} else if (element->size > node->size) { |
|
||||
node = node->right; |
|
||||
} else { |
|
||||
if (NULL != node->next) { |
|
||||
if (NULL != node->parent) { |
|
||||
if (node == node->parent->left) { |
|
||||
node->parent->left = node->next; |
|
||||
} else { |
|
||||
node->parent->right = node->next; |
|
||||
} |
|
||||
} else { |
|
||||
*tree = node->next; |
|
||||
} |
|
||||
|
|
||||
if (NULL != node->left) { |
|
||||
node->left->parent = node->next; |
|
||||
} |
|
||||
|
|
||||
if (NULL != node->right) { |
|
||||
node->right->parent = node->next; |
|
||||
} |
|
||||
|
|
||||
node->next->last = node->last; |
|
||||
node->next->color = node->color; |
|
||||
node->next->parent = node->parent; |
|
||||
node->next->left = node->left; |
|
||||
node->next->right = node->right; |
|
||||
|
|
||||
return node; |
|
||||
} |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// element not found |
|
||||
if (NULL == node) { |
|
||||
return node; |
|
||||
} |
|
||||
|
|
||||
del_node = node; |
|
||||
|
|
||||
// now our cases follows...the first one is the same as with |
|
||||
// simple binary search trees. Two non null children. |
|
||||
|
|
||||
// case 1: two children |
|
||||
if (NULL != node->left && NULL != node->right) { |
|
||||
struct element * successor = findInOrderSuccessor(node); |
|
||||
|
|
||||
enum rbColor tmpcolor = successor->color; |
|
||||
struct element * tmpparent = successor->parent; |
|
||||
struct element * tmpleft = successor->left; |
|
||||
struct element * tmpright = successor->right; |
|
||||
|
|
||||
replaceNode(tree, node, successor); |
|
||||
|
|
||||
successor->color = node->color; |
|
||||
successor->left = node->left; |
|
||||
successor->left->parent = successor; |
|
||||
// the right one might be successor... |
|
||||
if (node->right == successor) { |
|
||||
successor->right = node; |
|
||||
node->parent = successor; |
|
||||
} else { |
|
||||
successor->right = node->right; |
|
||||
node->right->parent = successor; |
|
||||
node->parent = tmpparent; |
|
||||
tmpparent->left = node; |
|
||||
} |
|
||||
|
|
||||
node->color = tmpcolor; |
|
||||
node->left = tmpleft; |
|
||||
node->right = tmpright; |
|
||||
} |
|
||||
|
|
||||
// Precondition: n has at most one non-null child. |
|
||||
child = (NULL == node->right) ? node->left : node->right; |
|
||||
replaceNode(tree, node, child); |
|
||||
|
|
||||
// delete one child case |
|
||||
// TODO this is overly complex as simply derived from the function... |
|
||||
// maybe this can be simplified. Maybe not...check. |
|
||||
if (node->color == rbBlack) { |
|
||||
if (NULL != child && child->color == rbRed) { |
|
||||
child->color = rbBlack; |
|
||||
// done despite modifying tree itself if neccessary.. |
|
||||
return del_node; |
|
||||
} else { |
|
||||
if (NULL != child) { |
|
||||
node = child; |
|
||||
} else { |
|
||||
node->color = rbBlack; |
|
||||
node->left = NULL; |
|
||||
node->right = NULL; |
|
||||
} |
|
||||
} |
|
||||
} else { |
|
||||
return del_node; |
|
||||
} |
|
||||
|
|
||||
// delete and rb rebalance... |
|
||||
while(1) { |
|
||||
// case 1 |
|
||||
if (NULL == node->parent) { |
|
||||
// done again |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
// case 2 |
|
||||
s = sibling(node); |
|
||||
|
|
||||
if (NULL != s && s->color == rbRed) { |
|
||||
node->parent->color = rbRed; |
|
||||
s->color = rbBlack; |
|
||||
|
|
||||
/* |
|
||||
* detect which child we are...assumption |
|
||||
* if we are not parent->right and parent->right is not |
|
||||
* null we must be left, even if its set to NULL previously |
|
||||
*/ |
|
||||
if (NULL != node->parent->right && node != node->parent->right) { |
|
||||
rotateLeft(tree, node->parent); |
|
||||
} else { |
|
||||
rotateRight(tree, node->parent); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
s = sibling(node); |
|
||||
// case 3 / 4 |
|
||||
if (NULL == s || ((s->color == rbBlack) && |
|
||||
(NULL == s->left || s->left->color == rbBlack) && |
|
||||
(NULL == s->right || s->right->color == rbBlack))) { |
|
||||
|
|
||||
if (NULL != s) { |
|
||||
s->color = rbRed; |
|
||||
} |
|
||||
|
|
||||
if (node->parent->color == rbBlack) { |
|
||||
// case 3 |
|
||||
node = node->parent; |
|
||||
continue; |
|
||||
} else { |
|
||||
// case 4 |
|
||||
node->parent->color = rbBlack; |
|
||||
// and done again... |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// case 5 |
|
||||
if (NULL != s && s->color == rbBlack) { |
|
||||
// this if statement is trivial, |
|
||||
// due to case 2 (even though case 2 changed the sibling to a |
|
||||
// sibling's child, |
|
||||
// the sibling's child can't be red, since no red parent can |
|
||||
// have a red child). |
|
||||
// |
|
||||
// the following statements just force the red to be on the |
|
||||
// left of the left of the parent, |
|
||||
// or right of the right, so case 6 will rotate correctly. |
|
||||
if ((node == node->parent->left) && |
|
||||
(NULL == s->right || s->right->color == rbBlack) && |
|
||||
(NULL != s->left && s->left->color == rbRed)) { |
|
||||
|
|
||||
// this last test is trivial too due to cases 2-4. |
|
||||
s->color = rbRed; |
|
||||
s->left->color = rbBlack; |
|
||||
|
|
||||
rotateRight(tree, s); |
|
||||
} else if ((node == node->parent->right) && |
|
||||
(NULL == s->left || s->left->color == rbBlack) && |
|
||||
(NULL != s->right && s->right->color == rbRed)) { |
|
||||
// this last test is trivial too due to cases 2-4. |
|
||||
s->color = rbRed; |
|
||||
s->right->color = rbBlack; |
|
||||
|
|
||||
rotateLeft(tree, s); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
s = sibling(node); |
|
||||
// case 6 |
|
||||
if (NULL != s) { |
|
||||
s->color = node->parent->color; |
|
||||
} |
|
||||
|
|
||||
if (NULL != node && NULL != node->parent) { |
|
||||
node->parent->color = rbBlack; |
|
||||
|
|
||||
/* |
|
||||
* detect which child we are...assumption |
|
||||
* if we are not parent->right and parent->right is not |
|
||||
* null we must be left, even if its set to NULL previously |
|
||||
*/ |
|
||||
if (NULL != node->parent->right && node != node->parent->right) { |
|
||||
if (NULL != s->right) { |
|
||||
s->right->color = rbBlack; |
|
||||
} |
|
||||
rotateLeft(tree, node->parent); |
|
||||
} else { |
|
||||
if (NULL != s->left) { |
|
||||
s->left->color = rbBlack; |
|
||||
} |
|
||||
rotateRight(tree, node->parent); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// done... |
|
||||
break; |
|
||||
} |
|
||||
|
|
||||
//deleteOneChild(tree, node); |
|
||||
|
|
||||
return del_node; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void |
|
||||
traverse(struct element * tree, void (*cb)(struct element *, int)) |
|
||||
{ |
|
||||
struct element * previous = tree; |
|
||||
struct element * node = tree; |
|
||||
int depth = 1; |
|
||||
|
|
||||
/* |
|
||||
* I think this has something like O(n+log(n)) on a ballanced |
|
||||
* tree because I have to traverse back the rightmost leaf to |
|
||||
* the root to get a break condition. |
|
||||
*/ |
|
||||
while (node) { |
|
||||
/* |
|
||||
* If we come from the right so nothing and go to our |
|
||||
* next parent. |
|
||||
*/ |
|
||||
if (previous == node->right) { |
|
||||
previous = node; |
|
||||
node = node->parent; |
|
||||
depth--; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if ((NULL == node->left || previous == node->left)) { |
|
||||
/* |
|
||||
* If there are no more elements to the left or we |
|
||||
* came from the left, process data. |
|
||||
*/ |
|
||||
cb(node, depth); |
|
||||
previous = node; |
|
||||
|
|
||||
if (NULL != node->right) { |
|
||||
node = node->right; |
|
||||
depth++; |
|
||||
} else { |
|
||||
node = node->parent; |
|
||||
depth--; |
|
||||
} |
|
||||
} else { |
|
||||
/* |
|
||||
* if there are more elements to the left go there. |
|
||||
*/ |
|
||||
previous = node; |
|
||||
node = node->left; |
|
||||
depth++; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
post(struct element * tree, void (*cb)(struct element *, int)) |
|
||||
{ |
|
||||
struct element * previous = tree; |
|
||||
struct element * node = tree; |
|
||||
int depth = 1; |
|
||||
|
|
||||
/* |
|
||||
* I think this has something like O(n+log(n)) on a ballanced |
|
||||
* tree because I have to traverse back the rightmost leaf to |
|
||||
* the root to get a break condition. |
|
||||
*/ |
|
||||
while (node) { |
|
||||
/* |
|
||||
* If we come from the right so nothing and go to our |
|
||||
* next parent. |
|
||||
*/ |
|
||||
if ((NULL == node->left && NULL == node->right) |
|
||||
|| previous == node->right) { |
|
||||
|
|
||||
struct element * parent = node->parent; |
|
||||
|
|
||||
cb(node, depth); |
|
||||
|
|
||||
previous = node; |
|
||||
node = parent; |
|
||||
depth--; |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
if ((NULL == node->left || previous == node->left)) { |
|
||||
/* |
|
||||
* If there are no more elements to the left or we |
|
||||
* came from the left, process data. |
|
||||
*/ |
|
||||
previous = node; |
|
||||
|
|
||||
if (NULL != node->right) { |
|
||||
node = node->right; |
|
||||
depth++; |
|
||||
} else { |
|
||||
node = node->parent; |
|
||||
depth--; |
|
||||
} |
|
||||
} else { |
|
||||
/* |
|
||||
* if there are more elements to the left go there. |
|
||||
*/ |
|
||||
previous = node; |
|
||||
node = node->left; |
|
||||
depth++; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void printElement(struct element * node, int depth) |
|
||||
{ |
|
||||
int i; |
|
||||
|
|
||||
printf("%s %010zu:%p(%02d)", |
|
||||
(node->color==rbRed)?"R":"B", |
|
||||
node->size, |
|
||||
node->ptr, |
|
||||
depth); |
|
||||
for (i=0; i<depth; i++) printf("-"); |
|
||||
puts(""); |
|
||||
|
|
||||
node = node->next; |
|
||||
while (NULL != node) { |
|
||||
printf(" %s %010zu:%p(%02d)", |
|
||||
(node->color==rbRed)?"R":"B", |
|
||||
node->size, |
|
||||
node->ptr, |
|
||||
depth); |
|
||||
for (i=0; i<depth; i++) printf("-"); |
|
||||
puts(""); |
|
||||
node = node->next; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void cleanup(struct element * node, int depth) |
|
||||
{ |
|
||||
while (NULL != node) { |
|
||||
printf("free node: "); |
|
||||
printElement(node, 0); |
|
||||
struct element * next = node->next; |
|
||||
free(node); |
|
||||
node = next; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* ======================================================================= |
|
||||
*/ |
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
struct element * root = NULL; |
|
||||
struct element * found = NULL; |
|
||||
|
|
||||
insertElement(&root, newElement(40)); |
|
||||
insertElement(&root, newElement(50)); |
|
||||
insertElement(&root, newElement(60)); |
|
||||
insertElement(&root, newElement(70)); |
|
||||
insertElement(&root, newElement(80)); |
|
||||
insertElement(&root, newElement(45)); |
|
||||
insertElement(&root, newElement(75)); |
|
||||
insertElement(&root, newElement(85)); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
insertElement(&root, newElement(70)); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
found = findElement(root, 10); |
|
||||
if (NULL == found) { |
|
||||
printf("can't find segmenet of minimum size: %d\n", 10); |
|
||||
} else { |
|
||||
printElement(found, 0); |
|
||||
} |
|
||||
puts(""); |
|
||||
|
|
||||
found = findElement(root, 64); |
|
||||
if (NULL == found) { |
|
||||
printf("can't find segmenet of minimum size: %d\n", 64); |
|
||||
} else { |
|
||||
printElement(found, 0); |
|
||||
} |
|
||||
puts(""); |
|
||||
|
|
||||
found = findElement(root, 90); |
|
||||
if (NULL == found) { |
|
||||
printf("can't find segmenet of minimum size: %d\n", 90); |
|
||||
} else { |
|
||||
printElement(found, 0); |
|
||||
} |
|
||||
puts(""); |
|
||||
|
|
||||
free(deleteElement(&root, findElement(root, 70))); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
insertElement(&root, newElement(80)); |
|
||||
insertElement(&root, newElement(50)); |
|
||||
insertElement(&root, newElement(80)); |
|
||||
|
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
found = deleteElement(&root, findElement(root, 80)); |
|
||||
printf("up to free: %p\n", found); |
|
||||
free(found); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
found = deleteElement(&root, findElement(root, 50)); |
|
||||
printf("up to free: %p\n", found); |
|
||||
free(found); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
found = deleteElement(&root, findElement(root, 70)); |
|
||||
printf("up to free: %p\n", found); |
|
||||
free(found); |
|
||||
puts("traverse"); |
|
||||
traverse(root, printElement); |
|
||||
puts(""); |
|
||||
|
|
||||
// post(root, cleanup); |
|
||||
// |
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,176 +0,0 @@ |
|||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
|
|
||||
#include "class.h" |
|
||||
#include "commons.h" |
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
#include "tree.h" |
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
#define NVALUES 10 |
|
||||
|
|
||||
int |
|
||||
insertCompare(const void * tval, const void * search) |
|
||||
{ |
|
||||
return *(const int *)tval - *(const int *)search; |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
freeNode(const void * data, const int depth) |
|
||||
{ |
|
||||
printf("now free %d at %p\n", *(int*)data, data); |
|
||||
MEM_FREE(data); |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
printNode(const void * _node, const int depth) |
|
||||
{ |
|
||||
Tree node = (Tree)_node; |
|
||||
int value = *(int *)node->data; |
|
||||
int i; |
|
||||
|
|
||||
for (i=1; i<7; i++) i<=depth?printf("-"):printf(" "); |
|
||||
printf("%p:%d p:%p l:%p r:%p\n", |
|
||||
node, value, node->parent, node->left, node->right); |
|
||||
|
|
||||
// printf("%s %010d(%02d)", |
|
||||
// (node->color==rbRed)?"R":"B", |
|
||||
// value, |
|
||||
// depth); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void * |
|
||||
newEle(int value) |
|
||||
{ |
|
||||
void * val = memMalloc(sizeof(int)); |
|
||||
|
|
||||
*(int*)val = value; |
|
||||
return val; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* ======================================================================= |
|
||||
*/ |
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
Tree root = NULL; |
|
||||
int * found = NULL; |
|
||||
int * element = NULL; |
|
||||
|
|
||||
int search10 = 10; |
|
||||
int search64 = 64; |
|
||||
int search70 = 70; |
|
||||
int search80 = 80; |
|
||||
int search50 = 50; |
|
||||
|
|
||||
treeInsert(&root, newEle(40), insertCompare); |
|
||||
treeInsert(&root, newEle(50), insertCompare); |
|
||||
treeInsert(&root, newEle(60), insertCompare); |
|
||||
treeInsert(&root, newEle(70), insertCompare); |
|
||||
treeInsert(&root, newEle(80), insertCompare); |
|
||||
treeInsert(&root, newEle(45), insertCompare); |
|
||||
treeInsert(&root, newEle(75), insertCompare); |
|
||||
treeInsert(&root, newEle(85), insertCompare); |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
element = newEle(70); |
|
||||
found = treeInsert(&root, element, insertCompare); |
|
||||
printf("insert %p(%d) got %p(%d)\n", element, *element, found, *found); |
|
||||
if (found != element) { |
|
||||
printf("remove duplicate"); |
|
||||
MEM_FREE(element); |
|
||||
} |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeFind(root, &search10, insertCompare); |
|
||||
if (NULL == found) { |
|
||||
printf("can't find segmenet of minimum size: %d\n", 10); |
|
||||
} else { |
|
||||
printf("found %d\n", *found); |
|
||||
} |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeFind(root, &search64, insertCompare); |
|
||||
if (NULL == found) { |
|
||||
printf("can't find segmenet of minimum size: %d\n", 64); |
|
||||
} else { |
|
||||
printf("found %d\n", *found); |
|
||||
} |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeFind(root, &search70, insertCompare); |
|
||||
if (NULL == found) { |
|
||||
printf("can't find segmenet of minimum size: %d\n", 70); |
|
||||
} else { |
|
||||
printf("found %d\n", *found); |
|
||||
} |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeDelete(&root, (void *)&search70, insertCompare); |
|
||||
printf("delete %p(%d) got %p(%d)\n", &search70, search70, found, *found); |
|
||||
MEM_FREE(found); |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeInsert(&root, (void *)&search80, insertCompare); |
|
||||
printf("insert %p(%d) got %p(%d)\n", &search80, search80, found, *found); |
|
||||
found = treeInsert(&root, (void *)&search50, insertCompare); |
|
||||
printf("insert %p(%d) got %p(%d)\n", &search50, search50, found, *found); |
|
||||
found = treeInsert(&root, (void *)&search80, insertCompare); |
|
||||
printf("insert %p(%d) got %p(%d)\n", &search80, search80, found, *found); |
|
||||
|
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeDelete(&root, (void *)&search80, insertCompare); |
|
||||
printf("delete %p(%d) got %p(%d)\n", &search80, search80, found, *found); |
|
||||
MEM_FREE(found); |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeDelete(&root, (void *)&search50, insertCompare); |
|
||||
printf("delete %p(%d) got %p(%d)\n", &search50, search50, found, *found); |
|
||||
MEM_FREE(found); |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
found = treeDelete(&root, (void *)&search70, insertCompare); |
|
||||
printf("delete %p(%d) got %p(%d)\n", &search70, search70, found, found?*found:-1); |
|
||||
MEM_FREE(found); |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
element = newEle(60); |
|
||||
found = treeDelete(&root, element, insertCompare); |
|
||||
printf("delete %p(%d) got %p(%d)\n", |
|
||||
element, |
|
||||
*element, |
|
||||
found, |
|
||||
found?*found:-1); |
|
||||
if (found != element) { |
|
||||
MEM_FREE(element); |
|
||||
} |
|
||||
MEM_FREE(found); |
|
||||
puts("traverse"); |
|
||||
treeWalk(root, printNode); |
|
||||
puts(""); |
|
||||
|
|
||||
treeDestroy(&root, freeNode); |
|
||||
memCleanup(); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,107 +0,0 @@ |
|||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
#include <gdbm.h> |
|
||||
#include <errno.h> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "class.h" |
|
||||
#include "commons.h" |
|
||||
#include "user.h" |
|
||||
#include "storage.h" |
|
||||
|
|
||||
#include "utils/memory.h" |
|
||||
|
|
||||
void |
|
||||
printUser(Storage users, const char * key, size_t nkey) |
|
||||
{ |
|
||||
User user = new(User, NULL); |
|
||||
|
|
||||
user->email = (char *)key, |
|
||||
user->nemail = &nkey; |
|
||||
|
|
||||
if (NULL == userLoad(user, users)) { |
|
||||
fprintf(stderr, "can't find user: %s\n", key); |
|
||||
} else { |
|
||||
puts("found user:"); |
|
||||
puts(user->email); |
|
||||
puts(user->firstname); |
|
||||
puts(user->surname); |
|
||||
|
|
||||
delete(user); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
void |
|
||||
insertUser( |
|
||||
Storage users, |
|
||||
const char * email, size_t nemail, |
|
||||
const char * firstname, size_t nfirstname, |
|
||||
const char * surname, size_t nsurname) |
|
||||
{ |
|
||||
User insert = new(User, |
|
||||
email, nemail, |
|
||||
firstname, nfirstname, |
|
||||
surname, nsurname); |
|
||||
|
|
||||
userSave(insert, users); |
|
||||
delete(insert); |
|
||||
} |
|
||||
|
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
Storage users = new(Storage, CSTRA("./users.db")); |
|
||||
|
|
||||
if (NULL == users) { |
|
||||
fprintf(stderr, "%s\n", gdbm_strerror(gdbm_errno)); |
|
||||
fprintf(stderr, "%s\n", strerror(errno)); |
|
||||
return 1; |
|
||||
} |
|
||||
|
|
||||
insertUser( |
|
||||
users, |
|
||||
CSTRA("georg"), |
|
||||
CSTRA("Georg"), |
|
||||
CSTRA("Hopp")); |
|
||||
insertUser( |
|
||||
users, |
|
||||
CSTRA("georg@steffers.org"), |
|
||||
CSTRA("Georg"), |
|
||||
CSTRA("Hopp")); |
|
||||
insertUser( |
|
||||
users, |
|
||||
CSTRA("drachenfrau1982@gmx.net"), |
|
||||
CSTRA("Gundula"), |
|
||||
CSTRA("Hopp")); |
|
||||
|
|
||||
printUser(users, CSTRA("foo@bar.de")); |
|
||||
puts(""); |
|
||||
printUser(users, CSTRA("drachenfrau1982@gmx.net")); |
|
||||
puts(""); |
|
||||
printUser(users, CSTRA("georg@steffers.org")); |
|
||||
|
|
||||
delete(users); |
|
||||
|
|
||||
users = new(Storage, CSTRA("./users.db")); |
|
||||
|
|
||||
insertUser( |
|
||||
users, |
|
||||
CSTRA("drachenfrau1982@gmx.net"), |
|
||||
CSTRA("Stefanie"), |
|
||||
CSTRA("Hopp")); |
|
||||
|
|
||||
puts(""); |
|
||||
printUser(users, CSTRA("foo@bar.de")); |
|
||||
puts(""); |
|
||||
printUser(users, CSTRA("drachenfrau1982@gmx.net")); |
|
||||
puts(""); |
|
||||
printUser(users, CSTRA("georg@steffers.org")); |
|
||||
|
|
||||
delete(users); |
|
||||
|
|
||||
memCleanup(); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set et ts=4 sw=4: |
|
||||
@ -1,18 +0,0 @@ |
|||||
#include <uuid/uuid.h> |
|
||||
#include <stdio.h> |
|
||||
|
|
||||
int |
|
||||
main(int argc, char * argv[]) |
|
||||
{ |
|
||||
uuid_t uuid; |
|
||||
char uuid_str[37]; |
|
||||
|
|
||||
uuid_generate(uuid); |
|
||||
uuid_unparse(uuid, uuid_str); |
|
||||
|
|
||||
printf("%s\n", uuid_str); |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// vim: set ts=4 sw=4: |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue