Add dict implementation
This commit is contained in:
		
							parent
							
								
									5c39f4970c
								
							
						
					
					
						commit
						2dcc673bb2
					
				
							
								
								
									
										210
									
								
								src/dict/base.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								src/dict/base.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,210 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
#define dtree_duplicate(s)    rbtree_duplicate((rbnode_t*)s, (void*)dnode_duplicate, nullptr)
 | 
			
		||||
#define dtree_compare(s0, s1) rbtree_compare((void*)s0, (void*)s1, (void*)dnode_compare, nullptr)
 | 
			
		||||
 | 
			
		||||
static dnode_t* dnode_duplicate(const dnode_t* s, dnode_t* p, void* not_used) {
 | 
			
		||||
    dnode_t* x;
 | 
			
		||||
 | 
			
		||||
    x           = dnode_create(vnode_duplicate(&s->key, s->key_type), p, s->colored);
 | 
			
		||||
    x->key_type = s->key_type;
 | 
			
		||||
    x->val_type = s->val_type;
 | 
			
		||||
    x->value    = vnode_duplicate(&s->value, s->val_type);
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int dnode_compare(const dnode_t *s0, const dnode_t *s1, void* not_used) {
 | 
			
		||||
    int c = vnode_compare(&s0->key, s1->key_type, &s1->key, s1->key_type);
 | 
			
		||||
 | 
			
		||||
    return (!c) ? vnode_compare(&s0->value, s1->val_type, &s1->value, s1->val_type) : c;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static hash_t dnode_hash(const dnode_t* s, void* not_used) {
 | 
			
		||||
    return vnode_hash(s->key, s->key_type) + vnode_hash(s->value, s->val_type) + s->key_type;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
static int dict_compare_equal_capacity(const dict_t* s0, const dict_t* s1) {
 | 
			
		||||
    int c;
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < s0->capacity; ++i) {
 | 
			
		||||
        if ((c = dtree_compare(s0->nodes[i], s1->nodes[i]))) {
 | 
			
		||||
            return c;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int dict_compare_unequal_capacity(const dict_t* s0, const dict_t* s1) {
 | 
			
		||||
    const dict_t *x, *y;
 | 
			
		||||
    dnode_t *c0, *c1;
 | 
			
		||||
    int cmp;
 | 
			
		||||
 | 
			
		||||
    stack_t z;
 | 
			
		||||
 | 
			
		||||
    if (s0->capacity <= s1->capacity) {
 | 
			
		||||
        x = s0;
 | 
			
		||||
        y = s1;
 | 
			
		||||
    } else {
 | 
			
		||||
        x = s1;
 | 
			
		||||
        y = s0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    z.prev  = 0;
 | 
			
		||||
    z.value = 0;
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < x->capacity; ++i) {
 | 
			
		||||
        if (!dnode_is_empty(x->nodes[i]))
 | 
			
		||||
            stack_push(&z, x->nodes[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((c0 = stack_pop(&z))) {
 | 
			
		||||
 | 
			
		||||
        c1  = y->nodes[vnode_hash(c0->key, c0->key_type) / y->capacity];
 | 
			
		||||
        cmp = 1;
 | 
			
		||||
 | 
			
		||||
        while (!dnode_is_empty(c1)) {
 | 
			
		||||
 | 
			
		||||
            cmp = vnode_compare(c0->key, c0->key_type, c1->key, c1->key_type);
 | 
			
		||||
 | 
			
		||||
            if (cmp == 0) break;
 | 
			
		||||
 | 
			
		||||
            c1 = (cmp < 0) ? c1->left : c1->right;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (cmp) return x == s0 ? cmp : ~cmp + 1;
 | 
			
		||||
 | 
			
		||||
        if (!dnode_is_empty(c0->right)) stack_push(&z, c0->right);
 | 
			
		||||
        if (!dnode_is_empty(c0->left))  stack_push(&z, c0->left);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
hash_t dict_hash(const dict_t* s) {
 | 
			
		||||
    dnode_t *l, *r;
 | 
			
		||||
    hash_t hash;
 | 
			
		||||
 | 
			
		||||
    if (!s->size) return 0;
 | 
			
		||||
 | 
			
		||||
    l = dnode_empty;
 | 
			
		||||
    r = dnode_empty;
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < s->capacity; ++i) {
 | 
			
		||||
        if (!dnode_is_empty(s->nodes[i])) {
 | 
			
		||||
            if (dnode_is_empty(l) || vnode_compare(s->nodes[i]->key, s->nodes[i]->key_type, l->key, l->key_type) < 0) {
 | 
			
		||||
                l = s->nodes[i];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (dnode_is_empty(r) || vnode_compare(s->nodes[i]->key, s->nodes[i]->key_type, r->key, r->key_type) > 0) {
 | 
			
		||||
                r = s->nodes[i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while (!dnode_is_empty(l->left))
 | 
			
		||||
        l = l->left;
 | 
			
		||||
 | 
			
		||||
    while (!dnode_is_empty(r->right))
 | 
			
		||||
        r = r->right;
 | 
			
		||||
 | 
			
		||||
    hash = vnode_hash(l->key, l->key_type) + vnode_hash(l->value, l->val_type);
 | 
			
		||||
 | 
			
		||||
    if (l != r) hash += vnode_hash(r->key, r->key_type) + vnode_hash(r->value, r->val_type);
 | 
			
		||||
 | 
			
		||||
    return (hash ^ s->size) + VTYPE_DICT;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dict_init(dict_t* x) {
 | 
			
		||||
    memset(x, 0, sizeof(*x));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void dict_free(dict_t* x) {
 | 
			
		||||
    for (size_t i = 0; i < x->capacity; ++i)
 | 
			
		||||
        rbtree_free(x->nodes[i], (void*)dnode_free, nullptr);
 | 
			
		||||
 | 
			
		||||
    free(x->nodes);
 | 
			
		||||
    memset(x, 0, sizeof(*x));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void libcdcb_dnode_free(dnode_t* x, void* not_used) {
 | 
			
		||||
    vnode_free(&x->key, x->key_type);
 | 
			
		||||
    vnode_free(&x->value, x->val_type);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
size_t dict_size(const dict_t* x) {
 | 
			
		||||
    return x->size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
size_t dict_capacity(const dict_t* x) {
 | 
			
		||||
    return x->capacity;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
int dict_compare(const dict_t* s0, const dict_t* s1) {
 | 
			
		||||
 | 
			
		||||
    if (s0 == s1)
 | 
			
		||||
        return 0;
 | 
			
		||||
 | 
			
		||||
    if (s0->size != s1->size)
 | 
			
		||||
        return s0->size < s1->size ? -1 : 1;
 | 
			
		||||
 | 
			
		||||
    if (s0->capacity == s1->capacity)
 | 
			
		||||
        return dict_compare_equal_capacity(s0, s1);
 | 
			
		||||
 | 
			
		||||
    return dict_compare_unequal_capacity(s0, s1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
dict_t dict_copy(const dict_t* s) {
 | 
			
		||||
    dict_t x;
 | 
			
		||||
 | 
			
		||||
    x.capacity = s->capacity;
 | 
			
		||||
    x.size     = s->size;
 | 
			
		||||
    x.nodes    = malloc(x.size * sizeof(*x.nodes));
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < x.capacity; ++i) {
 | 
			
		||||
        x.nodes[i] = dtree_duplicate(s->nodes[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
dict_t* dict_duplicate(const dict_t* s) {
 | 
			
		||||
    dict_t *x = malloc(sizeof(*x));
 | 
			
		||||
 | 
			
		||||
    x->capacity = s->capacity;
 | 
			
		||||
    x->size     = s->size;
 | 
			
		||||
    x->nodes    = malloc(x->size * sizeof(*x->nodes));
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < x->capacity; ++i) {
 | 
			
		||||
        x->nodes[i] = dtree_duplicate(s->nodes[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return x;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void dict_copy_init(dict_t* x, const dict_t* s) {
 | 
			
		||||
    x->capacity = s->capacity;
 | 
			
		||||
    x->size     = s->size;
 | 
			
		||||
    x->nodes    = malloc(x->size * sizeof(*x->nodes));
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < x->capacity; ++i) {
 | 
			
		||||
        x->nodes[i] = dtree_duplicate(s->nodes[i]);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										209
									
								
								src/dict/extra.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								src/dict/extra.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,209 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "include.h"
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
static void dict_rehash(dict_t* s, size_t capacity) {
 | 
			
		||||
    stack_t z;
 | 
			
		||||
    int cmp;
 | 
			
		||||
    dnode_t *c, *p, *n, **r;
 | 
			
		||||
 | 
			
		||||
    dnode_t **nodes = malloc(capacity * sizeof(*nodes));
 | 
			
		||||
 | 
			
		||||
    while (s->capacity--) {
 | 
			
		||||
        if (!dnode_is_empty(s->nodes[s->capacity]))
 | 
			
		||||
            stack_push(&z, s->nodes[s->capacity]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((c = stack_pop(&z))) {
 | 
			
		||||
 | 
			
		||||
        if (!dnode_is_empty(c->right)) {
 | 
			
		||||
            stack_push(&z, c->right);
 | 
			
		||||
            c->right = dnode_empty;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!dnode_is_empty(c->left)) {
 | 
			
		||||
            stack_push(&z, c->left);
 | 
			
		||||
            c->left = dnode_empty;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        n = *(r = &nodes[vnode_hash(c->key, c->key_type) / capacity]);
 | 
			
		||||
 | 
			
		||||
        if (!dnode_is_empty(*r)) {
 | 
			
		||||
            do {
 | 
			
		||||
                p   = n;
 | 
			
		||||
                cmp = vnode_compare(&c->key, c->key_type, &n->key, n->key_type);
 | 
			
		||||
                n   = (cmp <= 0) ? n->left : n->right;
 | 
			
		||||
            } while (!dnode_is_empty(n));
 | 
			
		||||
 | 
			
		||||
            if (cmp < 0) p->left  = c;
 | 
			
		||||
            else         p->right = c;
 | 
			
		||||
 | 
			
		||||
            c->parent  = p;
 | 
			
		||||
            c->colored = 1;
 | 
			
		||||
 | 
			
		||||
            if (!dnode_is_root(p))
 | 
			
		||||
                dnode_fixup(r, n);
 | 
			
		||||
 | 
			
		||||
        } else {
 | 
			
		||||
            *r         = c;
 | 
			
		||||
            c->colored = 0;
 | 
			
		||||
            c->parent  = dnode_empty;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    free(s->nodes);
 | 
			
		||||
 | 
			
		||||
    s->capacity = capacity;
 | 
			
		||||
    s->nodes    = nodes;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*#####################################################################################################################*/
 | 
			
		||||
 | 
			
		||||
bool libcdsb_dict_shrink_to_fit(dict_t* s) {
 | 
			
		||||
 | 
			
		||||
    size_t capacity;
 | 
			
		||||
 | 
			
		||||
    capacity  = (s->size / CAPACITY_BLOCK) + 1;
 | 
			
		||||
    capacity *= CAPACITY_BLOCK;
 | 
			
		||||
 | 
			
		||||
    while (((double)s->size / capacity) > 0.65)
 | 
			
		||||
        capacity += CAPACITY_BLOCK;
 | 
			
		||||
 | 
			
		||||
    if (capacity >= s->capacity)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    dict_rehash(s, capacity);
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
bool libcdsb_dict_update(dict_t* x, const void* k, vtype kt, const void* v, vtype vt) {
 | 
			
		||||
 | 
			
		||||
    dnode_t **r, *n, *p;
 | 
			
		||||
    vnode_t kn, vn;
 | 
			
		||||
    int cmp;
 | 
			
		||||
 | 
			
		||||
    if (!x->capacity || (double)x->size / x->capacity > REBUILD_POINT_MAX) {
 | 
			
		||||
        dict_rehash(x, x->capacity + CAPACITY_BLOCK);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    n  = *(r = &x->nodes[vnode_hash(k, kt) / x->capacity]);
 | 
			
		||||
    kn = vnode_create(k, kt);
 | 
			
		||||
    vn = vnode_create(v, vt);
 | 
			
		||||
 | 
			
		||||
    if (!dnode_is_empty(n)) {
 | 
			
		||||
        do {
 | 
			
		||||
            p   = n;
 | 
			
		||||
            cmp = vtype_compare(k, kt, vnode_peek(&n->key, n->key_type), n->key_type);
 | 
			
		||||
 | 
			
		||||
            if (cmp == 0) {
 | 
			
		||||
                dnode_free(n, nullptr);
 | 
			
		||||
 | 
			
		||||
                n->key      = kn;
 | 
			
		||||
                n->value    = vn;
 | 
			
		||||
                n->key_type = kt;
 | 
			
		||||
                n->val_type = vt;
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            n = (cmp < 0) ? n->left : n->right;
 | 
			
		||||
        } while (!dnode_is_empty(n));
 | 
			
		||||
 | 
			
		||||
        n = dnode_create(kn, p, 1);
 | 
			
		||||
 | 
			
		||||
        if (cmp < 0) p->left  = n;
 | 
			
		||||
        else         p->right = n;
 | 
			
		||||
 | 
			
		||||
        if (!dnode_is_root(p))
 | 
			
		||||
            dnode_fixup(r, n);
 | 
			
		||||
 | 
			
		||||
    } else n = *r = dnode_create(kn, dnode_empty, 0);
 | 
			
		||||
 | 
			
		||||
    n->value    = vn;
 | 
			
		||||
    n->key_type = kt;
 | 
			
		||||
    n->val_type = vt;
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int libcdsb_dict_get(dict_t* x, const void* k, vtype t, void* _, dict_access_callback callback, bool cut) {
 | 
			
		||||
 | 
			
		||||
    dnode_t *c, **r;
 | 
			
		||||
    void* key;
 | 
			
		||||
    int cmp;
 | 
			
		||||
 | 
			
		||||
    if (x->capacity) {
 | 
			
		||||
        c = *(r = &x->nodes[vnode_hash(k, t) / x->capacity]);
 | 
			
		||||
 | 
			
		||||
        while (!dnode_is_empty(c)) {
 | 
			
		||||
            key = vnode_peek(&c->key, c->key_type);
 | 
			
		||||
            cmp = vtype_compare(k, t, key, c->key_type);
 | 
			
		||||
 | 
			
		||||
            if (cmp == 0) {
 | 
			
		||||
                cmp = (callback) ? callback(key, t, vnode_peek(&c->value, c->val_type), c->val_type, _) : 0;
 | 
			
		||||
 | 
			
		||||
                if (cut) {
 | 
			
		||||
                    c = dnode_delete(r, c);
 | 
			
		||||
                    dnode_free(c, nullptr);
 | 
			
		||||
                    free(c);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return cmp;
 | 
			
		||||
            } else c = (cmp < 0) ? c->left : c->right;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int libcdsb_dict_foreach(dict_t* x, void* dt, dict_access_callback callback, bool flush) {
 | 
			
		||||
    stack_t z;
 | 
			
		||||
    int r;
 | 
			
		||||
    dnode_t* c;
 | 
			
		||||
 | 
			
		||||
    r       = 0;
 | 
			
		||||
    z.prev  = 0;
 | 
			
		||||
    z.value = 0;
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < x->capacity; ++i) {
 | 
			
		||||
        if (!dnode_is_empty(x->nodes[i]))
 | 
			
		||||
            stack_push(&z, x->nodes[i]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while ((c = stack_pop(&z))) {
 | 
			
		||||
        if ((r = callback(vnode_peek(&c->key, c->key_type), c->key_type, vnode_peek(&c->value, c->val_type), c->val_type, dt)))
 | 
			
		||||
            break;
 | 
			
		||||
 | 
			
		||||
        if (!dnode_is_empty(c->right)) stack_push(&z, c->right);
 | 
			
		||||
        if (!dnode_is_empty(c->left))  stack_push(&z, c->left);
 | 
			
		||||
 | 
			
		||||
        if (flush) {
 | 
			
		||||
            dnode_free(c, nullptr);
 | 
			
		||||
            free(c);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (flush) {
 | 
			
		||||
        while (c) {
 | 
			
		||||
            if (!dnode_is_empty(c->right)) stack_push(&z, c->right);
 | 
			
		||||
            if (!dnode_is_empty(c->left))  stack_push(&z, c->left);
 | 
			
		||||
 | 
			
		||||
            dnode_free(c, nullptr);
 | 
			
		||||
            free(c);
 | 
			
		||||
 | 
			
		||||
            c = stack_pop(&z);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        free(x->nodes);
 | 
			
		||||
        memset(x, 0, sizeof(*x));
 | 
			
		||||
    } else stack_flush(&z);
 | 
			
		||||
 | 
			
		||||
    return r;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										45
									
								
								src/dict/include.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/dict/include.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
/* This software is licensed by the MIT License, see LICENSE file */
 | 
			
		||||
/*                                Copyright © 2022 Gregory Lirent */
 | 
			
		||||
 | 
			
		||||
#include "../../include/extra/dict.h"
 | 
			
		||||
#include "../__internal/assert.h"
 | 
			
		||||
#include "../__internal/rbtree.h"
 | 
			
		||||
 | 
			
		||||
#ifndef LIBCDSB_SRC_DICT_INCLUDE_H
 | 
			
		||||
#define LIBCDSB_SRC_DICT_INCLUDE_H
 | 
			
		||||
 | 
			
		||||
#define CAPACITY_BLOCK   100
 | 
			
		||||
#define REBUILD_POINT_MAX 0.65
 | 
			
		||||
#define REBUILD_POINT_MIN  1
 | 
			
		||||
 | 
			
		||||
typedef struct libcdsb_dict_node {
 | 
			
		||||
    struct libcdsb_dict_node* left;
 | 
			
		||||
    struct libcdsb_dict_node* right;
 | 
			
		||||
    struct libcdsb_dict_node* parent;
 | 
			
		||||
 | 
			
		||||
    vnode_t key;
 | 
			
		||||
    short   colored;
 | 
			
		||||
    u8_t    key_type;
 | 
			
		||||
    u8_t    val_type;
 | 
			
		||||
    vnode_t value;
 | 
			
		||||
} dnode_t;
 | 
			
		||||
 | 
			
		||||
static_assert(offsetof(struct libcdsb_rbtree_node, left) == offsetof(struct libcdsb_dict_node, left), "Implementation assert");
 | 
			
		||||
static_assert(offsetof(struct libcdsb_rbtree_node, right) == offsetof(struct libcdsb_dict_node, right), "Implementation assert");
 | 
			
		||||
static_assert(offsetof(struct libcdsb_rbtree_node, parent) == offsetof(struct libcdsb_dict_node, parent), "Implementation assert");
 | 
			
		||||
static_assert(offsetof(struct libcdsb_rbtree_node, colored) == offsetof(struct libcdsb_dict_node, colored), "Implementation assert");
 | 
			
		||||
static_assert(offsetof(struct libcdsb_rbtree_node, value) == offsetof(struct libcdsb_dict_node, key), "Implementation assert");
 | 
			
		||||
 | 
			
		||||
#define dnode_empty           ((dnode_t*)LIBCDSB_RBTREE_NODE_EMPTY)
 | 
			
		||||
#define dnode_create(k, p, c) ((dnode_t*)libcdsb_rbtree_node_create(k, (rbnode_t*)p, c, sizeof(dnode_t)))
 | 
			
		||||
#define dnode_fixup(r, n)     libcdsb_rbtree_node_fixup((rbnode_t**)(r), (rbnode_t*)(n))
 | 
			
		||||
#define dnode_delete(r, n)    (dnode_t*)libcdsb_rbtree_node_delete((rbnode_t**)(r), (rbnode_t*)(n))
 | 
			
		||||
 | 
			
		||||
#define dnode_is_empty(n) ((n) == dnode_empty)
 | 
			
		||||
#define dnode_is_root(n)  dnode_is_empty((n)->parent)
 | 
			
		||||
 | 
			
		||||
extern void libcdcb_dnode_free(dnode_t* x, void* not_used);
 | 
			
		||||
 | 
			
		||||
#define dnode_free libcdcb_dnode_free
 | 
			
		||||
 | 
			
		||||
#endif /* LIBCDSB_SRC_MAP_INCLUDE_H */
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user