dutil: Convert strlist to use rb_trees

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2009-06-18 14:02:29 -03:00
parent 5ad2e36d32
commit 1009bc9fe7
2 changed files with 97 additions and 32 deletions

113
dutil.c
View File

@ -11,7 +11,6 @@
#include <ctype.h>
#include <errno.h>
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -24,30 +23,61 @@ void *zalloc(const size_t size)
return s;
}
static int str_compare(const void *a, const void *b)
struct str_node *str_node__new(const char *s, bool dupstr)
{
return strcmp(a, b);
struct str_node *self = malloc(sizeof(*self));
if (self != NULL){
if (dupstr) {
s = strdup(s);
if (s == NULL)
goto out_delete;
}
self->s = s;
}
return self;
out_delete:
free(self);
return NULL;
}
int strlist__add(struct strlist *self, const char *str)
static void str_node__delete(struct str_node *self, bool dupstr)
{
const char **s = tsearch(str, &self->entries, str_compare);
if (dupstr)
free((void *)self->s);
free(self);
}
if (s != NULL) {
if (*s == str) {
const char *dup = self->dupstr ? strdup(str) : str;
int strlist__add(struct strlist *self, const char *new_entry)
{
struct rb_node **p = &self->entries.rb_node;
struct rb_node *parent = NULL;
struct str_node *sn;
if (dup != NULL)
*s = dup;
else {
tdelete(str, &self->entries, str_compare);
return -ENOMEM;
}
} else
while (*p != NULL) {
int rc;
parent = *p;
sn = rb_entry(parent, struct str_node, rb_node);
rc = strcmp(sn->s, new_entry);
if (rc > 0)
p = &(*p)->rb_left;
else if (rc < 0)
p = &(*p)->rb_right;
else
return -EEXIST;
} else
}
sn = str_node__new(new_entry, self->dupstr);
if (sn == NULL)
return -ENOMEM;
rb_link_node(&sn->rb_node, parent, p);
rb_insert_color(&sn->rb_node, &self->entries);
return 0;
}
@ -82,34 +112,57 @@ struct strlist *strlist__new(bool dupstr)
struct strlist *self = malloc(sizeof(*self));
if (self != NULL) {
self->entries = NULL;
self->entries = RB_ROOT;
self->dupstr = dupstr;
}
return self;
}
static void do_nothing(void *ptr __unused)
{
}
void strlist__delete(struct strlist *self)
{
if (self != NULL) {
if (self->dupstr)
tdestroy(self->entries, free);
else
tdestroy(self->entries, do_nothing);
self->entries = NULL;
struct str_node *pos;
struct rb_node *next = rb_first(&self->entries);
while (next) {
pos = rb_entry(next, struct str_node, rb_node);
next = rb_next(&pos->rb_node);
strlist__remove(self, pos);
}
self->entries = RB_ROOT;
free(self);
}
}
int strlist__has_entry(const struct strlist *self, const char *entry)
void strlist__remove(struct strlist *self, struct str_node *sn)
{
if (self == NULL)
return false;
return tfind(entry, &self->entries, str_compare) != NULL;
rb_erase(&sn->rb_node, &self->entries);
str_node__delete(sn, self->dupstr);
}
bool strlist__has_entry(struct strlist *self, const char *entry)
{
struct rb_node **p = &self->entries.rb_node;
struct rb_node *parent = NULL;
while (*p != NULL) {
struct str_node *sn;
int rc;
parent = *p;
sn = rb_entry(parent, struct str_node, rb_node);
rc = strcmp(sn->s, entry);
if (rc > 0)
p = &(*p)->rb_left;
else if (rc < 0)
p = &(*p)->rb_right;
else
return true;
}
return false;
}
Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,

16
dutil.h
View File

@ -15,6 +15,7 @@
#include <stddef.h>
#include <elf.h>
#include <gelf.h>
#include "rbtree.h"
#ifndef __unused
#define __unused __attribute__ ((unused))
@ -42,18 +43,29 @@ static inline __attribute__((const)) bool is_power_of_2(unsigned long n)
#define ARGP_PROGRAM_BUG_ADDRESS_DEF \
const char *const apba__ __asm ("argp_program_bug_address")
struct str_node {
struct rb_node rb_node;
const char *s;
};
struct strlist {
void *entries;
struct rb_root entries;
bool dupstr;
};
struct strlist *strlist__new(bool dupstr);
void strlist__delete(struct strlist *self);
void strlist__remove(struct strlist *self, struct str_node *sn);
int strlist__load(struct strlist *self, const char *filename);
int strlist__add(struct strlist *self, const char *str);
int strlist__has_entry(const struct strlist *self, const char *entry);
bool strlist__has_entry(struct strlist *self, const char *entry);
static inline bool strlist__empty(const struct strlist *self)
{
return rb_first(&self->entries) == NULL;
}
void *zalloc(const size_t size);