Get rid of flags member in spdylay_map

This commit is contained in:
Tatsuhiro Tsujikawa 2012-10-05 23:41:49 +09:00
parent 24e932dfa2
commit 46e7da2166
3 changed files with 97 additions and 59 deletions

View File

@ -24,12 +24,6 @@
*/ */
#include "spdylay_map.h" #include "spdylay_map.h"
typedef enum {
SUB_LEFT = 1,
SUB_RIGHT = 1 << 1,
SUB_ALL = (1 << 2) - 1
} spdylay_map_subtr;
void spdylay_map_init(spdylay_map *map) void spdylay_map_init(spdylay_map *map)
{ {
map->root = NULL; map->root = NULL;
@ -41,31 +35,102 @@ void spdylay_map_free(spdylay_map *map)
map->root = NULL; map->root = NULL;
} }
/* Find left most node, which is not necessarily a leaf. */
static spdylay_map_entry* find_left_most(spdylay_map_entry *entry)
{
while(entry->left) {
entry = entry->left;
}
return entry;
}
/* Find left most leaf. */
static spdylay_map_entry* find_left_most_leaf(spdylay_map_entry *entry)
{
for(;;) {
entry = find_left_most(entry);
if(entry->right) {
entry = entry->right;
} else {
break;
}
}
return entry;
}
/* Returns next node in postorder traversal. Returns NULL if there is
no next node. */
static spdylay_map_entry* traverse_postorder(spdylay_map_entry *parent,
spdylay_map_entry *entry)
{
if(!parent) {
return NULL;
}
if(parent->left == entry) {
if(parent->right) {
return find_left_most_leaf(parent->right);
} else {
return parent;
}
} else {
return parent;
}
}
void spdylay_map_each_free(spdylay_map *map, void spdylay_map_each_free(spdylay_map *map,
int (*func)(spdylay_map_entry *entry, void *ptr), int (*func)(spdylay_map_entry *entry, void *ptr),
void *ptr) void *ptr)
{ {
spdylay_map_entry *entry = map->root; spdylay_map_entry *entry;
if(!map->root) {
return;
}
entry = find_left_most_leaf(map->root);
while(entry) { while(entry) {
if(entry->flags == SUB_ALL) {
spdylay_map_entry *parent = entry->parent; spdylay_map_entry *parent = entry->parent;
/* Ignore return value. */
func(entry, ptr); func(entry, ptr);
entry = parent; /* entry has been deleted. */
} else if(entry->flags == SUB_LEFT) { entry = traverse_postorder(parent, entry);
entry->flags |= SUB_RIGHT;
if(entry->right) {
entry = entry->right;
}
} else {
entry->flags |= SUB_LEFT;
if(entry->left) {
entry = entry->left;
}
}
} }
map->root = NULL; map->root = NULL;
} }
/* Returns next node in inorder traversal. Returns NULL if there is no
next node. */
static spdylay_map_entry* traverse_inorder(spdylay_map_entry *entry)
{
spdylay_map_entry *parent;
if(entry->right) {
return find_left_most(entry->right);
}
parent = entry->parent;
while(parent && parent->right == entry) {
entry = entry->parent;
parent = parent->parent;
}
return parent;
}
int spdylay_map_each(spdylay_map *map,
int (*func)(spdylay_map_entry *entry, void *ptr),
void *ptr)
{
spdylay_map_entry *entry;
if(!map->root) {
return 0;
}
entry = find_left_most(map->root);
while(entry) {
int rv = func(entry, ptr);
if(rv != 0) {
return rv;
}
entry = traverse_inorder(entry);
}
return 0;
}
/* /*
* 32 bit Mix Functions by Thomas Wang * 32 bit Mix Functions by Thomas Wang
* *
@ -87,7 +152,6 @@ void spdylay_map_entry_init(spdylay_map_entry *entry, key_type key)
entry->key = key; entry->key = key;
entry->parent = entry->left = entry->right = NULL; entry->parent = entry->left = entry->right = NULL;
entry->priority = hash32shift(key); entry->priority = hash32shift(key);
entry->flags = 0;
} }
static spdylay_map_entry* rotate_left(spdylay_map_entry *entry) static spdylay_map_entry* rotate_left(spdylay_map_entry *entry)
@ -270,36 +334,3 @@ size_t spdylay_map_size(spdylay_map *map)
{ {
return map->size; return map->size;
} }
int spdylay_map_each(spdylay_map *map,
int (*func)(spdylay_map_entry *entry, void *ptr),
void *ptr)
{
spdylay_map_entry *entry = map->root;
while(entry) {
if(entry->flags == SUB_ALL) {
entry->flags = 0;
entry = entry->parent;
} else if(entry->flags == SUB_LEFT) {
int rv;
rv = func(entry, ptr);
if(rv != 0) {
while(entry) {
entry->flags = 0;
entry = entry->parent;
}
return rv;
}
entry->flags |= SUB_RIGHT;
if(entry->right) {
entry = entry->right;
}
} else {
entry->flags |= SUB_LEFT;
if(entry->left) {
entry = entry->left;
}
}
}
return 0;
}

View File

@ -41,7 +41,6 @@ typedef struct spdylay_map_entry {
key_type key; key_type key;
struct spdylay_map_entry *parent, *left, *right; struct spdylay_map_entry *parent, *left, *right;
pri_type priority; pri_type priority;
uint8_t flags;
} spdylay_map_entry; } spdylay_map_entry;
typedef struct { typedef struct {

View File

@ -125,7 +125,7 @@ void test_spdylay_map_functional(void)
// insertion // insertion
shuffle(order, NUM_ENT); shuffle(order, NUM_ENT);
for(i = 0; i < NUM_ENT; ++i) { for(i = 0; i < NUM_ENT; ++i) {
CU_ASSERT(0 == spdylay_map_insert(&map, &arr[i].map_entry)); CU_ASSERT(0 == spdylay_map_insert(&map, &arr[order[i] - 1].map_entry));
} }
// traverse // traverse
spdylay_map_each(&map, eachfun, NULL); spdylay_map_each(&map, eachfun, NULL);
@ -140,7 +140,15 @@ void test_spdylay_map_functional(void)
CU_ASSERT(0 == spdylay_map_remove(&map, order[i])); CU_ASSERT(0 == spdylay_map_remove(&map, order[i]));
} }
spdylay_map_free(&map); // each_free (but no op function for testing purpose)
for(i = 0; i < NUM_ENT; ++i) {
strentry_init(&arr[i], i + 1, "foo");
}
// insert once again
for(i = 0; i < NUM_ENT; ++i) {
CU_ASSERT(0 == spdylay_map_insert(&map, &arr[i].map_entry));
}
spdylay_map_each_free(&map, eachfun, NULL);
} }
static int entry_free(spdylay_map_entry *entry, void *ptr) static int entry_free(spdylay_map_entry *entry, void *ptr)