packio
changeset 0:a71bd70c1014
simple pack-file I/O library
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 03 Jan 2015 15:29:05 +0200 |
parents | |
children | a5728bc6a02f |
files | .hgignore Makefile include/packio.h src/packio.c src/pathmap.c src/pathmap.h src/rbtree.c src/rbtree.h |
diffstat | 8 files changed, 741 insertions(+), 0 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Sat Jan 03 15:29:05 2015 +0200 1.3 @@ -0,0 +1,4 @@ 1.4 +\.o$ 1.5 +\.swp$ 1.6 +\.d$ 1.7 +^libpackio.a$
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Makefile Sat Jan 03 15:29:05 2015 +0200 2.3 @@ -0,0 +1,24 @@ 2.4 +PREFIX = /usr/local 2.5 + 2.6 +src = $(wildcard src/*.c) 2.7 +obj = $(src:.c=.o) 2.8 +dep = $(obj:.o=.d) 2.9 +name = packio 2.10 + 2.11 +lib_a = lib$(name).a 2.12 + 2.13 +inc = -Iinclude 2.14 + 2.15 +CFLAGS = -pedantic -Wall -g $(pic) $(inc) 2.16 + 2.17 +$(lib_a): $(obj) 2.18 + $(AR) rcs $@ $(obj) 2.19 + 2.20 +-include $(dep) 2.21 + 2.22 +%.d: %.c 2.23 + @$(CPP) $(CFLAGS) $< -MM -MT $(@:.d=.o) >$@ 2.24 + 2.25 +.PHONY: clean 2.26 +clean: 2.27 + rm -f $(obj) $(dep) $(lib_a)
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/include/packio.h Sat Jan 03 15:29:05 2015 +0200 3.3 @@ -0,0 +1,59 @@ 3.4 +#ifndef PACKIO_H_ 3.5 +#define PACKIO_H_ 3.6 + 3.7 +typedef struct pkio_file PKIO_FILE; 3.8 +typedef struct pkio_dir PKIO_DIR; 3.9 + 3.10 +#define PKIO_MAX_NAME 256 3.11 +struct pkio_dirent { 3.12 + char d_name[PKIO_MAX_NAME]; 3.13 +}; 3.14 + 3.15 +struct pkio_stat { 3.16 + unsigned int st_mode; 3.17 + unsigned long st_size; 3.18 +}; 3.19 + 3.20 +#ifdef __cplusplus 3.21 +extern "C" { 3.22 +#endif 3.23 + 3.24 +extern int pkio_errno; 3.25 + 3.26 +int pkio_fopen(const char *path); 3.27 +int pkio_fclose(PKIO_FILE *fp); 3.28 + 3.29 +int pkio_fseek(PKIO_FILE *fp, long offset, int whence); 3.30 +long pkio_ftell(PKIO_FILE *fp); 3.31 +void pkio_rewind(PKIO_FILE *fp); 3.32 + 3.33 +size_t pkio_fread(void *buf, size_t size, size_t nitems, PKIO_FILE *fp); 3.34 +size_t pkio_fwrite(void *buf, size_t size, size_t nitems, PKIO_FILE *fp); 3.35 + 3.36 +int pkio_fgetc(PKIO_FILE *fp); 3.37 +int pkio_fputc(int c, PKIO_FILE *fp); 3.38 + 3.39 +char *pkio_fgets(char *buf, int size, PKIO_FILE *fp); 3.40 +int pkio_fputs(char *buf, PKIO_FILE *fp); 3.41 + 3.42 +int pkio_fscanf(PKIO_FILE *fp, const char *fmt, ...); 3.43 +int pkio_vfscanf(PKIO_FILE *fp, const char *fmt, va_list ap); 3.44 +int pkio_fprintf(PKIO_FILE *fp, const char *fmt, ...); 3.45 +int pkio_vfprintf(PKIO_FILE *fp, const char *fmt, va_list ap); 3.46 + 3.47 +void pkio_clearerr(PKIO_FILE *fp); 3.48 +int pkio_feof(PKIO_FILE *fp); 3.49 +int pkio_ferror(PKIO_FILE *fp); 3.50 + 3.51 +PKIO_DIR *pkio_opendir(const char *dirname); 3.52 +int pkio_closedir(PKIO_DIR *dir); 3.53 +struct pkio_dirent *pkio_readdir(PKIO_DIR *dir); 3.54 +void pkio_rewinddir(PKIO_DIR *dir); 3.55 + 3.56 +int pkio_stat(const char *path, struct pkio_stat *buf); 3.57 + 3.58 +#ifdef __cplusplus 3.59 +} 3.60 +#endif 3.61 + 3.62 +#endif /* PACKIO_H_ */
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/packio.c Sat Jan 03 15:29:05 2015 +0200 4.3 @@ -0,0 +1,6 @@ 4.4 +#include <stdio.h> 4.5 +#include "packio.h" 4.6 + 4.7 +int pkio_fopen(const char *path) 4.8 +{ 4.9 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/src/pathmap.c Sat Jan 03 15:29:05 2015 +0200 5.3 @@ -0,0 +1,62 @@ 5.4 +#include <stdio.h> 5.5 +#include <stdlib.h> 5.6 +#include <string.h> 5.7 +#include "pathmap.h" 5.8 +#include "rbtree.h" 5.9 + 5.10 +static void map_entry_destructor(struct rbnode *node, void *data); 5.11 + 5.12 +static struct rbtree *map; 5.13 + 5.14 +int pkio_map(const char *from, const char *to) 5.15 +{ 5.16 + char *myfrom, *myto; 5.17 + 5.18 + if(!map) { 5.19 + if(!(map = rb_create(RB_KEY_STRING))) { 5.20 + fprintf(stderr, "packio: failed to create path mapping tree\n"); 5.21 + return -1; 5.22 + } 5.23 + rb_set_delete_func(map, map_entry_destructor, 0); 5.24 + } 5.25 + 5.26 + if(!(myfrom = malloc(strlen(from) + 1))) { 5.27 + fprintf(stderr, "packio: failed to allocate mapping source string\n"); 5.28 + return -1; 5.29 + } 5.30 + if(!(myto = malloc(strlen(to) + 1))) { 5.31 + fprintf(stderr, "packio: failed to allocate mapping destination string\n"); 5.32 + free(myto); 5.33 + return -1; 5.34 + } 5.35 + strcpy(myfrom, from); 5.36 + strcpy(myto, to); 5.37 + 5.38 + if(rb_insert(map, myfrom, myto) == -1) { 5.39 + fprintf(stderr, "packio: failed to add path mapping\n"); 5.40 + free(myfrom); 5.41 + free(myto); 5.42 + return -1; 5.43 + } 5.44 + return 0; 5.45 +} 5.46 + 5.47 +const char *pkio_pathmap(const char *path) 5.48 +{ 5.49 + struct rbnode *node; 5.50 + 5.51 + if(!map) { 5.52 + return path; 5.53 + } 5.54 + 5.55 + if(!(node = rb_find(map, (void*)path))) { 5.56 + return path; 5.57 + } 5.58 + return node->data; 5.59 +} 5.60 + 5.61 +static void map_entry_destructor(struct rbnode *node, void *data) 5.62 +{ 5.63 + free(node->key); 5.64 + free(node->data); 5.65 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/pathmap.h Sat Jan 03 15:29:05 2015 +0200 6.3 @@ -0,0 +1,7 @@ 6.4 +#ifndef PATH_MAP_H_ 6.5 +#define PATH_MAP_H_ 6.6 + 6.7 +int pkio_map(const char *from, const char *to); 6.8 +const char *pkio_pathmap(const char *path); 6.9 + 6.10 +#endif /* PATH_MAP_H_ */
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/src/rbtree.c Sat Jan 03 15:29:05 2015 +0200 7.3 @@ -0,0 +1,501 @@ 7.4 +/* 7.5 +rbtree - simple balanced binary search tree (red-black tree) library. 7.6 +Copyright (C) 2011-2014 John Tsiombikas <nuclear@member.fsf.org> 7.7 + 7.8 +rbtree is free software, feel free to use, modify, and redistribute it, under 7.9 +the terms of the 3-clause BSD license. See COPYING for details. 7.10 + */ 7.11 +#include <stdio.h> 7.12 +#include <stdlib.h> 7.13 +#include <stdint.h> 7.14 +#include <string.h> 7.15 +#include "rbtree.h" 7.16 + 7.17 +#define INT2PTR(x) ((void*)(intptr_t)(x)) 7.18 +#define PTR2INT(x) ((int)(intptr_t)(x)) 7.19 + 7.20 +struct rbtree { 7.21 + struct rbnode *root; 7.22 + 7.23 + rb_alloc_func_t alloc; 7.24 + rb_free_func_t free; 7.25 + 7.26 + rb_cmp_func_t cmp; 7.27 + rb_del_func_t del; 7.28 + void *del_cls; 7.29 + 7.30 + struct rbnode *rstack, *iter; 7.31 +}; 7.32 + 7.33 +static int cmpaddr(const void *ap, const void *bp); 7.34 +static int cmpint(const void *ap, const void *bp); 7.35 + 7.36 +static int count_nodes(struct rbnode *node); 7.37 +static void del_tree(struct rbnode *node, void (*delfunc)(struct rbnode*, void*), void *cls); 7.38 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data); 7.39 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key); 7.40 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key);*/ 7.41 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls); 7.42 + 7.43 +struct rbtree *rb_create(rb_cmp_func_t cmp_func) 7.44 +{ 7.45 + struct rbtree *rb; 7.46 + 7.47 + if(!(rb = malloc(sizeof *rb))) { 7.48 + return 0; 7.49 + } 7.50 + if(rb_init(rb, cmp_func) == -1) { 7.51 + free(rb); 7.52 + return 0; 7.53 + } 7.54 + return rb; 7.55 +} 7.56 + 7.57 +void rb_free(struct rbtree *rb) 7.58 +{ 7.59 + rb_destroy(rb); 7.60 + free(rb); 7.61 +} 7.62 + 7.63 + 7.64 +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func) 7.65 +{ 7.66 + memset(rb, 0, sizeof *rb); 7.67 + 7.68 + if(!cmp_func) { 7.69 + rb->cmp = cmpaddr; 7.70 + } else if(cmp_func == RB_KEY_INT) { 7.71 + rb->cmp = cmpint; 7.72 + } else if(cmp_func == RB_KEY_STRING) { 7.73 + rb->cmp = (rb_cmp_func_t)strcmp; 7.74 + } else { 7.75 + rb->cmp = cmp_func; 7.76 + } 7.77 + 7.78 + rb->alloc = malloc; 7.79 + rb->free = free; 7.80 + return 0; 7.81 +} 7.82 + 7.83 +void rb_destroy(struct rbtree *rb) 7.84 +{ 7.85 + del_tree(rb->root, rb->del, rb->del_cls); 7.86 +} 7.87 + 7.88 +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free) 7.89 +{ 7.90 + rb->alloc = alloc; 7.91 + rb->free = free; 7.92 +} 7.93 + 7.94 + 7.95 +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func) 7.96 +{ 7.97 + rb->cmp = func; 7.98 +} 7.99 + 7.100 +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls) 7.101 +{ 7.102 + rb->del = func; 7.103 + rb->del_cls = cls; 7.104 +} 7.105 + 7.106 + 7.107 +void rb_clear(struct rbtree *rb) 7.108 +{ 7.109 + del_tree(rb->root, rb->del, rb->del_cls); 7.110 + rb->root = 0; 7.111 +} 7.112 + 7.113 +int rb_copy(struct rbtree *dest, struct rbtree *src) 7.114 +{ 7.115 + struct rbnode *node; 7.116 + 7.117 + rb_clear(dest); 7.118 + rb_begin(src); 7.119 + while((node = rb_next(src))) { 7.120 + if(rb_insert(dest, node->key, node->data) == -1) { 7.121 + return -1; 7.122 + } 7.123 + } 7.124 + return 0; 7.125 +} 7.126 + 7.127 +int rb_size(struct rbtree *rb) 7.128 +{ 7.129 + return count_nodes(rb->root); 7.130 +} 7.131 + 7.132 +int rb_insert(struct rbtree *rb, void *key, void *data) 7.133 +{ 7.134 + rb->root = insert(rb, rb->root, key, data); 7.135 + rb->root->red = 0; 7.136 + return 0; 7.137 +} 7.138 + 7.139 +int rb_inserti(struct rbtree *rb, int key, void *data) 7.140 +{ 7.141 + rb->root = insert(rb, rb->root, INT2PTR(key), data); 7.142 + rb->root->red = 0; 7.143 + return 0; 7.144 +} 7.145 + 7.146 + 7.147 +int rb_delete(struct rbtree *rb, void *key) 7.148 +{ 7.149 + rb->root = delete(rb, rb->root, key); 7.150 + rb->root->red = 0; 7.151 + return 0; 7.152 +} 7.153 + 7.154 +int rb_deletei(struct rbtree *rb, int key) 7.155 +{ 7.156 + rb->root = delete(rb, rb->root, INT2PTR(key)); 7.157 + rb->root->red = 0; 7.158 + return 0; 7.159 +} 7.160 + 7.161 + 7.162 +struct rbnode *rb_find(struct rbtree *rb, void *key) 7.163 +{ 7.164 + struct rbnode *node = rb->root; 7.165 + 7.166 + while(node) { 7.167 + int cmp = rb->cmp(key, node->key); 7.168 + if(cmp == 0) { 7.169 + return node; 7.170 + } 7.171 + node = cmp < 0 ? node->left : node->right; 7.172 + } 7.173 + return 0; 7.174 +} 7.175 + 7.176 +struct rbnode *rb_findi(struct rbtree *rb, int key) 7.177 +{ 7.178 + return rb_find(rb, INT2PTR(key)); 7.179 +} 7.180 + 7.181 + 7.182 +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls) 7.183 +{ 7.184 + traverse(rb->root, func, cls); 7.185 +} 7.186 + 7.187 + 7.188 +struct rbnode *rb_root(struct rbtree *rb) 7.189 +{ 7.190 + return rb->root; 7.191 +} 7.192 + 7.193 +void rb_begin(struct rbtree *rb) 7.194 +{ 7.195 + rb->rstack = 0; 7.196 + rb->iter = rb->root; 7.197 +} 7.198 + 7.199 +#define push(sp, x) ((x)->next = (sp), (sp) = (x)) 7.200 +#define pop(sp) ((sp) = (sp)->next) 7.201 +#define top(sp) (sp) 7.202 + 7.203 +struct rbnode *rb_next(struct rbtree *rb) 7.204 +{ 7.205 + struct rbnode *res = 0; 7.206 + 7.207 + while(rb->rstack || rb->iter) { 7.208 + if(rb->iter) { 7.209 + push(rb->rstack, rb->iter); 7.210 + rb->iter = rb->iter->left; 7.211 + } else { 7.212 + rb->iter = top(rb->rstack); 7.213 + pop(rb->rstack); 7.214 + res = rb->iter; 7.215 + rb->iter = rb->iter->right; 7.216 + break; 7.217 + } 7.218 + } 7.219 + return res; 7.220 +} 7.221 + 7.222 +void *rb_node_key(struct rbnode *node) 7.223 +{ 7.224 + return node ? node->key : 0; 7.225 +} 7.226 + 7.227 +int rb_node_keyi(struct rbnode *node) 7.228 +{ 7.229 + return node ? PTR2INT(node->key) : 0; 7.230 +} 7.231 + 7.232 +void *rb_node_data(struct rbnode *node) 7.233 +{ 7.234 + return node ? node->data : 0; 7.235 +} 7.236 + 7.237 +static int cmpaddr(const void *ap, const void *bp) 7.238 +{ 7.239 + return ap < bp ? -1 : (ap > bp ? 1 : 0); 7.240 +} 7.241 + 7.242 +static int cmpint(const void *ap, const void *bp) 7.243 +{ 7.244 + return PTR2INT(ap) - PTR2INT(bp); 7.245 +} 7.246 + 7.247 + 7.248 +/* ---- left-leaning 2-3 red-black implementation ---- */ 7.249 + 7.250 +/* helper prototypes */ 7.251 +static int is_red(struct rbnode *tree); 7.252 +static void color_flip(struct rbnode *tree); 7.253 +static struct rbnode *rot_left(struct rbnode *a); 7.254 +static struct rbnode *rot_right(struct rbnode *a); 7.255 +static struct rbnode *find_min(struct rbnode *tree); 7.256 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree); 7.257 +/*static struct rbnode *move_red_right(struct rbnode *tree);*/ 7.258 +static struct rbnode *move_red_left(struct rbnode *tree); 7.259 +static struct rbnode *fix_up(struct rbnode *tree); 7.260 + 7.261 +static int count_nodes(struct rbnode *node) 7.262 +{ 7.263 + if(!node) 7.264 + return 0; 7.265 + 7.266 + return 1 + count_nodes(node->left) + count_nodes(node->right); 7.267 +} 7.268 + 7.269 +static void del_tree(struct rbnode *node, rb_del_func_t delfunc, void *cls) 7.270 +{ 7.271 + if(!node) 7.272 + return; 7.273 + 7.274 + del_tree(node->left, delfunc, cls); 7.275 + del_tree(node->right, delfunc, cls); 7.276 + 7.277 + if(delfunc) { 7.278 + delfunc(node, cls); 7.279 + } 7.280 + free(node); 7.281 +} 7.282 + 7.283 +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data) 7.284 +{ 7.285 + int cmp; 7.286 + 7.287 + if(!tree) { 7.288 + struct rbnode *node = rb->alloc(sizeof *node); 7.289 + node->red = 1; 7.290 + node->key = key; 7.291 + node->data = data; 7.292 + node->left = node->right = 0; 7.293 + return node; 7.294 + } 7.295 + 7.296 + cmp = rb->cmp(key, tree->key); 7.297 + 7.298 + if(cmp < 0) { 7.299 + tree->left = insert(rb, tree->left, key, data); 7.300 + } else if(cmp > 0) { 7.301 + tree->right = insert(rb, tree->right, key, data); 7.302 + } else { 7.303 + tree->data = data; 7.304 + } 7.305 + 7.306 + /* fix right-leaning reds */ 7.307 + if(is_red(tree->right)) { 7.308 + tree = rot_left(tree); 7.309 + } 7.310 + /* fix two reds in a row */ 7.311 + if(is_red(tree->left) && is_red(tree->left->left)) { 7.312 + tree = rot_right(tree); 7.313 + } 7.314 + 7.315 + /* if 4-node, split it by color inversion */ 7.316 + if(is_red(tree->left) && is_red(tree->right)) { 7.317 + color_flip(tree); 7.318 + } 7.319 + 7.320 + return tree; 7.321 +} 7.322 + 7.323 +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key) 7.324 +{ 7.325 + int cmp; 7.326 + 7.327 + if(!tree) { 7.328 + return 0; 7.329 + } 7.330 + 7.331 + cmp = rb->cmp(key, tree->key); 7.332 + 7.333 + if(cmp < 0) { 7.334 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 7.335 + tree = move_red_left(tree); 7.336 + } 7.337 + tree->left = delete(rb, tree->left, key); 7.338 + } else { 7.339 + /* need reds on the right */ 7.340 + if(is_red(tree->left)) { 7.341 + tree = rot_right(tree); 7.342 + } 7.343 + 7.344 + /* found it at the bottom (XXX what certifies left is null?) */ 7.345 + if(cmp == 0 && !tree->right) { 7.346 + if(rb->del) { 7.347 + rb->del(tree, rb->del_cls); 7.348 + } 7.349 + rb->free(tree); 7.350 + return 0; 7.351 + } 7.352 + 7.353 + if(!is_red(tree->right) && !is_red(tree->right->left)) { 7.354 + tree = move_red_left(tree); 7.355 + } 7.356 + 7.357 + if(key == tree->key) { 7.358 + struct rbnode *rmin = find_min(tree->right); 7.359 + tree->key = rmin->key; 7.360 + tree->data = rmin->data; 7.361 + tree->right = del_min(rb, tree->right); 7.362 + } else { 7.363 + tree->right = delete(rb, tree->right, key); 7.364 + } 7.365 + } 7.366 + 7.367 + return fix_up(tree); 7.368 +} 7.369 + 7.370 +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key) 7.371 +{ 7.372 + int cmp; 7.373 + 7.374 + if(!node) 7.375 + return 0; 7.376 + 7.377 + if((cmp = rb->cmp(key, node->key)) == 0) { 7.378 + return node; 7.379 + } 7.380 + return find(rb, cmp < 0 ? node->left : node->right, key); 7.381 +}*/ 7.382 + 7.383 +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls) 7.384 +{ 7.385 + if(!node) 7.386 + return; 7.387 + 7.388 + traverse(node->left, func, cls); 7.389 + func(node, cls); 7.390 + traverse(node->right, func, cls); 7.391 +} 7.392 + 7.393 +/* helpers */ 7.394 + 7.395 +static int is_red(struct rbnode *tree) 7.396 +{ 7.397 + return tree && tree->red; 7.398 +} 7.399 + 7.400 +static void color_flip(struct rbnode *tree) 7.401 +{ 7.402 + tree->red = !tree->red; 7.403 + tree->left->red = !tree->left->red; 7.404 + tree->right->red = !tree->right->red; 7.405 +} 7.406 + 7.407 +static struct rbnode *rot_left(struct rbnode *a) 7.408 +{ 7.409 + struct rbnode *b = a->right; 7.410 + a->right = b->left; 7.411 + b->left = a; 7.412 + b->red = a->red; 7.413 + a->red = 1; 7.414 + return b; 7.415 +} 7.416 + 7.417 +static struct rbnode *rot_right(struct rbnode *a) 7.418 +{ 7.419 + struct rbnode *b = a->left; 7.420 + a->left = b->right; 7.421 + b->right = a; 7.422 + b->red = a->red; 7.423 + a->red = 1; 7.424 + return b; 7.425 +} 7.426 + 7.427 +static struct rbnode *find_min(struct rbnode *tree) 7.428 +{ 7.429 + if(!tree) 7.430 + return 0; 7.431 + 7.432 + while(tree->left) { 7.433 + tree = tree->left; 7.434 + } 7.435 + return tree; 7.436 +} 7.437 + 7.438 +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree) 7.439 +{ 7.440 + if(!tree->left) { 7.441 + if(rb->del) { 7.442 + rb->del(tree->left, rb->del_cls); 7.443 + } 7.444 + rb->free(tree->left); 7.445 + return 0; 7.446 + } 7.447 + 7.448 + /* make sure we've got red (3/4-nodes) at the left side so we can delete at the bottom */ 7.449 + if(!is_red(tree->left) && !is_red(tree->left->left)) { 7.450 + tree = move_red_left(tree); 7.451 + } 7.452 + tree->left = del_min(rb, tree->left); 7.453 + 7.454 + /* fix right-reds, red-reds, and split 4-nodes on the way up */ 7.455 + return fix_up(tree); 7.456 +} 7.457 + 7.458 +#if 0 7.459 +/* push a red link on this node to the right */ 7.460 +static struct rbnode *move_red_right(struct rbnode *tree) 7.461 +{ 7.462 + /* flipping it makes both children go red, so we have a red to the right */ 7.463 + color_flip(tree); 7.464 + 7.465 + /* if after the flip we've got a red-red situation to the left, fix it */ 7.466 + if(is_red(tree->left->left)) { 7.467 + tree = rot_right(tree); 7.468 + color_flip(tree); 7.469 + } 7.470 + return tree; 7.471 +} 7.472 +#endif 7.473 + 7.474 +/* push a red link on this node to the left */ 7.475 +static struct rbnode *move_red_left(struct rbnode *tree) 7.476 +{ 7.477 + /* flipping it makes both children go red, so we have a red to the left */ 7.478 + color_flip(tree); 7.479 + 7.480 + /* if after the flip we've got a red-red on the right-left, fix it */ 7.481 + if(is_red(tree->right->left)) { 7.482 + tree->right = rot_right(tree->right); 7.483 + tree = rot_left(tree); 7.484 + color_flip(tree); 7.485 + } 7.486 + return tree; 7.487 +} 7.488 + 7.489 +static struct rbnode *fix_up(struct rbnode *tree) 7.490 +{ 7.491 + /* fix right-leaning */ 7.492 + if(is_red(tree->right)) { 7.493 + tree = rot_left(tree); 7.494 + } 7.495 + /* change invalid red-red pairs into a proper 4-node */ 7.496 + if(is_red(tree->left) && is_red(tree->left->left)) { 7.497 + tree = rot_right(tree); 7.498 + } 7.499 + /* split 4-nodes */ 7.500 + if(is_red(tree->left) && is_red(tree->right)) { 7.501 + color_flip(tree); 7.502 + } 7.503 + return tree; 7.504 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/src/rbtree.h Sat Jan 03 15:29:05 2015 +0200 8.3 @@ -0,0 +1,78 @@ 8.4 +/* 8.5 +rbtree - simple balanced binary search tree (red-black tree) library. 8.6 +Copyright (C) 2011-2014 John Tsiombikas <nuclear@member.fsf.org> 8.7 + 8.8 +rbtree is free software, feel free to use, modify, and redistribute it, under 8.9 +the terms of the 3-clause BSD license. See COPYING for details. 8.10 + */ 8.11 +#ifndef RBTREE_H_ 8.12 +#define RBTREE_H_ 8.13 + 8.14 +struct rbtree; 8.15 + 8.16 + 8.17 +struct rbnode { 8.18 + void *key, *data; 8.19 + int red; 8.20 + struct rbnode *left, *right; 8.21 + struct rbnode *next; /* for iterator stack */ 8.22 +}; 8.23 + 8.24 + 8.25 +typedef void *(*rb_alloc_func_t)(size_t); 8.26 +typedef void (*rb_free_func_t)(void*); 8.27 + 8.28 +typedef int (*rb_cmp_func_t)(const void*, const void*); 8.29 +typedef void (*rb_del_func_t)(struct rbnode*, void*); 8.30 + 8.31 +#define RB_KEY_ADDR (rb_cmp_func_t)(0) 8.32 +#define RB_KEY_INT (rb_cmp_func_t)(1) 8.33 +#define RB_KEY_STRING (rb_cmp_func_t)(3) 8.34 + 8.35 + 8.36 +#ifdef __cplusplus 8.37 +extern "C" { 8.38 +#endif 8.39 + 8.40 +struct rbtree *rb_create(rb_cmp_func_t cmp_func); 8.41 +void rb_free(struct rbtree *rb); 8.42 + 8.43 +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func); 8.44 +void rb_destroy(struct rbtree *rb); 8.45 + 8.46 +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free); 8.47 +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func); 8.48 +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls); 8.49 +/* TODO add user deep copy function */ 8.50 + 8.51 +void rb_clear(struct rbtree *rb); 8.52 +int rb_copy(struct rbtree *dest, struct rbtree *src); 8.53 + 8.54 +int rb_size(struct rbtree *rb); 8.55 + 8.56 +int rb_insert(struct rbtree *rb, void *key, void *data); 8.57 +int rb_inserti(struct rbtree *rb, int key, void *data); 8.58 + 8.59 +int rb_delete(struct rbtree *rb, void *key); 8.60 +int rb_deletei(struct rbtree *rb, int key); 8.61 + 8.62 +struct rbnode *rb_find(struct rbtree *rb, void *key); 8.63 +struct rbnode *rb_findi(struct rbtree *rb, int key); 8.64 + 8.65 +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls); 8.66 + 8.67 +struct rbnode *rb_root(struct rbtree *rb); 8.68 + 8.69 +void rb_begin(struct rbtree *rb); 8.70 +struct rbnode *rb_next(struct rbtree *rb); 8.71 + 8.72 +void *rb_node_key(struct rbnode *node); 8.73 +int rb_node_keyi(struct rbnode *node); 8.74 +void *rb_node_data(struct rbnode *node); 8.75 + 8.76 +#ifdef __cplusplus 8.77 +} 8.78 +#endif 8.79 + 8.80 + 8.81 +#endif /* RBTREE_H_ */