From: Michael D. Lowis Date: Wed, 3 Sep 2014 00:23:30 +0000 (-0400) Subject: Merge from dev X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=efca1902c925547638ecd47a522dbf38132eb6b8;p=projs%2Flibcds.git Merge from dev --- efca1902c925547638ecd47a522dbf38132eb6b8 diff --cc Rakefile index cdecb62,cce8899..5c88c39 --- a/Rakefile +++ b/Rakefile @@@ -24,7 -24,8 +24,7 @@@ en TestEnv = Env.clone do |env| env.build_dir('source','build/obj/test_source') env.build_dir('tests','build/obj/tests/source') - env['CFLAGS'] += ['-DLEAK_DETECT_LEVEL=1', '--coverage'] + env['CFLAGS'] += ['-g', '--coverage', '-DLEAK_DETECT_LEVEL=1', '-DTESTING'] - #env['CFLAGS'] += ['-DNDEBUG'] #disables asserts so they won't effect coverage analysis env["LDFLAGS"] += ['--coverage'] env['CPPPATH'] += Dir['tests/'] end diff --cc source/cursor/cursor.h index 0000000,0000000..d23e797 new file mode 100644 --- /dev/null +++ b/source/cursor/cursor.h @@@ -1,0 -1,0 +1,39 @@@ ++/** ++ @file cursor.h ++ @brief Generic cursor module for moving over data structures. ++ $Revision$ ++ $HeadURL$ ++ */ ++#ifndef CURSOR_H ++#define CURSOR_H ++ ++#include "mem.h" ++ ++typedef enum { ++ FORWARD, ++ BACKWARD ++} advance_dir_t; ++ ++typedef bool (*tester_t)(void* env, advance_dir_t dir); ++ ++typedef void (*advancer_t)(void* env, advance_dir_t dir); ++ ++typedef void* (*getter_t)(void* env); ++ ++typedef void (*setter_t)(void* env, void* val); ++ ++struct crsr_t; ++ ++typedef struct crsr_t crsr_t; ++ ++crsr_t* crsr_new(void* p_state, tester_t p_test, advancer_t p_advance, getter_t p_get, setter_t p_set); ++crsr_t* crsr_copy(crsr_t* p_crsr); ++void crsr_advance(crsr_t* p_crsr, int steps); ++void crsr_next(crsr_t* p_crsr); ++void crsr_prev(crsr_t* p_crsr); ++bool crsr_has_next(crsr_t* p_crsr); ++bool crsr_has_prev(crsr_t* p_crsr); ++void* crsr_get(crsr_t* p_crsr); ++void crsr_set(crsr_t* p_crsr, void* val); ++ ++#endif /* CURSOR_H */ diff --cc source/rbt/rbt.c index 8e42fc9,4d426ac..b17f3ac --- a/source/rbt/rbt.c +++ b/source/rbt/rbt.c @@@ -19,8 -15,9 +19,9 @@@ static int rbt_default_comparator(void /* rbt_t */ static void rbt_free(void* v_tree){ - rbt_t* tree = (rbt_t*) v_tree; - assert(NULL != tree); - if(tree->root) mem_release(tree->root); + rbt_t* tree = (rbt_t*) v_tree; - if(tree && tree->root) mem_release(tree->root); ++ assert(NULL != tree); ++ if(tree->root) mem_release(tree->root); } rbt_t* rbt_new(comparator_t comparator){ @@@ -32,32 -29,36 +33,36 @@@ /* rbt_node_t */ static void rbt_node_free(void* v_node){ - rbt_node_t* node = (rbt_node_t*) v_node; - assert(NULL != node); - mem_release(node->contents); - if(node->left) mem_release(node->left); - if(node->right) mem_release(node->right); + rbt_node_t* node = (rbt_node_t*) v_node; - if(node){ - mem_release(node->contents); - if(node->left) mem_release(node->left); - if(node->right) mem_release(node->right); - } ++ assert(NULL != node); ++ mem_release(node->contents); ++ if(node->left) mem_release(node->left); ++ if(node->right) mem_release(node->right); } + #ifndef TESTING + static + #endif rbt_node_t* rbt_node_new(void* contents){ - rbt_node_t* node = mem_allocate(sizeof(rbt_node_t), &rbt_node_free); - node->left = NULL; - node->right = NULL; - node->parent = NULL; - node->contents = contents; - node->color = RED; - return node; + rbt_node_t* node = mem_allocate(sizeof(rbt_node_t), &rbt_node_free); + node->left = NULL; + node->right = NULL; + node->parent = NULL; + node->contents = contents; + node->color = RED; + return node; } /* ---------------------------------------- */ /* informational / querying functions */ /* ---------------------------------------- */ - + #ifndef TESTING + static + #endif rbt_color_t rbt_node_color(rbt_node_t* node){ - //leaves are NULL and black implicitly - return (node ? node->color : BLACK); + //leaves are NULL and black implicitly + return (node ? node->color : BLACK); } static rbt_node_t* rbt_lookup_node(rbt_t* tree, rbt_node_t* node, void* value){ @@@ -80,12 -81,14 +85,13 @@@ static rbt_node_t* rightmost_descendant } static int rbt_count(rbt_node_t* node){ - return (!node ? 0 : (1 + rbt_count(node->left) + rbt_count(node->right))); + return (!node ? 0 : (1 + rbt_count(node->left) + rbt_count(node->right))); } - int rbt_count_nodes(rbt_t* tree){ + + int rbt_size(rbt_t* tree){ - return rbt_count(tree->root); + return rbt_count(tree->root); } - /* ----------------------------------------- */ /* generally helpful tree manipulation */ /* ----------------------------------------- */ @@@ -102,16 -105,15 +108,15 @@@ typedef enum } direction_t; static void rbt_rotate(rbt_t* tree, rbt_node_t* node, direction_t direction){ - rbt_node_t* edon = (direction == LEFT) ? node->right : node->left; - assert(NULL != edon); - rbt_node_t** edon_side = (direction == LEFT ? &(edon->left) : &(edon->right)); - rbt_node_t** node_side = (direction == LEFT ? &(node->right) : &(node->left)); - rbt_node_replace(tree, node, edon); - *node_side = *edon_side; //safe to overwrite; points to edon - if(*edon_side) (*edon_side)->parent = node; - *edon_side = node; - node->parent = edon; + rbt_node_t* edon = (direction == LEFT) ? node->right : node->left; - if(edon){ - rbt_node_t** edon_side = (direction == LEFT ? &(edon->left) : &(edon->right)); - rbt_node_t** node_side = (direction == LEFT ? &(node->right) : &(node->left)); - rbt_node_replace(tree, node, edon); - *node_side = *edon_side; //safe to overwrite; points to edon - if(*edon_side) (*edon_side)->parent = node; - *edon_side = node; - node->parent = edon; - } /* else rotation isn't allowed */ ++ assert(NULL != edon); ++ rbt_node_t** edon_side = (direction == LEFT ? &(edon->left) : &(edon->right)); ++ rbt_node_t** node_side = (direction == LEFT ? &(node->right) : &(node->left)); ++ rbt_node_replace(tree, node, edon); ++ *node_side = *edon_side; //safe to overwrite; points to edon ++ if(*edon_side) (*edon_side)->parent = node; ++ *edon_side = node; ++ node->parent = edon; } @@@ -120,11 -122,12 +125,12 @@@ /* -------------------- */ static void rbt_ins_rebalance(rbt_t* tree, rbt_node_t* node, direction_t heavy_side){ - rbt_node_t* parent = node->parent; - assert(NULL != parent); - rbt_node_t* grandparent = parent->parent; - rbt_rotate(tree, grandparent, (heavy_side == LEFT ? RIGHT : LEFT)); - parent->color = BLACK; - grandparent->color = RED; + rbt_node_t* parent = node->parent; - rbt_node_t* grandparent = (parent ? parent->parent : NULL); ++ assert(NULL != parent); ++ rbt_node_t* grandparent = parent->parent; + rbt_rotate(tree, grandparent, (heavy_side == LEFT ? RIGHT : LEFT)); + parent->color = BLACK; + grandparent->color = RED; } static void rbt_ins_recolor(rbt_t* tree, rbt_node_t* node){ @@@ -169,51 -172,50 +175,49 @@@ static void rbt_insert_node(rbt_t* tree } rbt_node_t* rbt_insert(rbt_t* tree, void* value){ - rbt_node_t* new_node = rbt_node_new(value); - rbt_insert_node(tree, new_node, tree->root); - return new_node; + rbt_node_t* new_node = rbt_node_new(value); + rbt_insert_node(tree, new_node, tree->root); + return new_node; } -- /* ------------------- */ /* removal code */ /* ------------------- */ //node has a count -1 of black nodes to leaves relative to the rest of the tree static void rbt_del_rebalance(rbt_t* tree, rbt_node_t* node){ - rbt_node_t* parent = node->parent; - if(parent){ - direction_t node_side = (node == parent->left ? LEFT : RIGHT); - rbt_node_t* sib = (node_side == LEFT ? parent->right : parent->left); - assert(NULL != sib); - //nibling: gender neutral term for niece or nephew. - rbt_node_t* inside_nibling = node_side == LEFT ? sib->left : sib->right; - rbt_node_t* outside_nibling = node_side == LEFT ? sib->right : sib->left; - if(RED == rbt_node_color(sib)){ - //rotate so sib is black & recurse w/ new scenario - rbt_rotate(tree, parent, node_side); - parent->color = RED; - sib->color = BLACK; - rbt_del_rebalance(tree, node); - }else if(BLACK == rbt_node_color(inside_nibling) && BLACK == rbt_node_color(outside_nibling)){ - //both niblings are black ; can paint sib red & rebalance on parent - sib->color = RED; - if(RED == rbt_node_color(parent)) parent->color = BLACK; - else rbt_del_rebalance(tree, parent); - }else if(BLACK == rbt_node_color(outside_nibling)){ - //convert "inside" case to "outside" case & recurse w/ new scenario - rbt_rotate(tree, sib, (node_side == LEFT ? RIGHT : LEFT)); - sib->color = RED; - inside_nibling->color = BLACK; - rbt_del_rebalance(tree, node); - }else{ - rbt_rotate(tree, parent, node_side); - sib->color = parent->color; - parent->color = BLACK; - outside_nibling->color = BLACK; - } - } + rbt_node_t* parent = node->parent; + if(parent){ + direction_t node_side = (node == parent->left ? LEFT : RIGHT); + rbt_node_t* sib = (node_side == LEFT ? parent->right : parent->left); ++ assert(NULL != sib); + //nibling: gender neutral term for niece or nephew. - rbt_node_t* inside_nibling = sib ? (node_side == LEFT ? sib->left : sib->right) : NULL; - rbt_node_t* outside_nibling = sib ? (node_side == LEFT ? sib->right : sib->left) : NULL; ++ rbt_node_t* inside_nibling = node_side == LEFT ? sib->left : sib->right; ++ rbt_node_t* outside_nibling = node_side == LEFT ? sib->right : sib->left; + if(RED == rbt_node_color(sib)){ + //rotate so sib is black & recurse w/ new scenario + rbt_rotate(tree, parent, node_side); + parent->color = RED; + sib->color = BLACK; + rbt_del_rebalance(tree, node); + }else if(BLACK == rbt_node_color(inside_nibling) && BLACK == rbt_node_color(outside_nibling)){ + //both niblings are black ; can paint sib red & rebalance on parent + sib->color = RED; + if(RED == rbt_node_color(parent)) parent->color = BLACK; + else rbt_del_rebalance(tree, parent); + }else if(BLACK == rbt_node_color(outside_nibling)){ + //convert "inside" case to "outside" case & recurse w/ new scenario + rbt_rotate(tree, sib, (node_side == LEFT ? RIGHT : LEFT)); + sib->color = RED; + inside_nibling->color = BLACK; + rbt_del_rebalance(tree, node); + }else{ + rbt_rotate(tree, parent, node_side); + sib->color = parent->color; + parent->color = BLACK; + outside_nibling->color = BLACK; + } - }else{ - node->color = BLACK; //TODO: verify this is necessary + } } static void rbt_delete_node(rbt_t* tree, rbt_node_t* node){