diff options
Diffstat (limited to 'tools/perf/util/rblist.c')
| -rw-r--r-- | tools/perf/util/rblist.c | 128 | 
1 files changed, 128 insertions, 0 deletions
diff --git a/tools/perf/util/rblist.c b/tools/perf/util/rblist.c new file mode 100644 index 00000000000..0dfe27d9945 --- /dev/null +++ b/tools/perf/util/rblist.c @@ -0,0 +1,128 @@ +/* + * Based on strlist.c by: + * (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com> + * + * Licensed under the GPLv2. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> + +#include "rblist.h" + +int rblist__add_node(struct rblist *rblist, const void *new_entry) +{ +	struct rb_node **p = &rblist->entries.rb_node; +	struct rb_node *parent = NULL, *new_node; + +	while (*p != NULL) { +		int rc; + +		parent = *p; + +		rc = rblist->node_cmp(parent, new_entry); +		if (rc > 0) +			p = &(*p)->rb_left; +		else if (rc < 0) +			p = &(*p)->rb_right; +		else +			return -EEXIST; +	} + +	new_node = rblist->node_new(rblist, new_entry); +	if (new_node == NULL) +		return -ENOMEM; + +	rb_link_node(new_node, parent, p); +	rb_insert_color(new_node, &rblist->entries); +	++rblist->nr_entries; + +	return 0; +} + +void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node) +{ +	rb_erase(rb_node, &rblist->entries); +	--rblist->nr_entries; +	rblist->node_delete(rblist, rb_node); +} + +static struct rb_node *__rblist__findnew(struct rblist *rblist, +					 const void *entry, +					 bool create) +{ +	struct rb_node **p = &rblist->entries.rb_node; +	struct rb_node *parent = NULL, *new_node = NULL; + +	while (*p != NULL) { +		int rc; + +		parent = *p; + +		rc = rblist->node_cmp(parent, entry); +		if (rc > 0) +			p = &(*p)->rb_left; +		else if (rc < 0) +			p = &(*p)->rb_right; +		else +			return parent; +	} + +	if (create) { +		new_node = rblist->node_new(rblist, entry); +		if (new_node) { +			rb_link_node(new_node, parent, p); +			rb_insert_color(new_node, &rblist->entries); +			++rblist->nr_entries; +		} +	} + +	return new_node; +} + +struct rb_node *rblist__find(struct rblist *rblist, const void *entry) +{ +	return __rblist__findnew(rblist, entry, false); +} + +struct rb_node *rblist__findnew(struct rblist *rblist, const void *entry) +{ +	return __rblist__findnew(rblist, entry, true); +} + +void rblist__init(struct rblist *rblist) +{ +	if (rblist != NULL) { +		rblist->entries	 = RB_ROOT; +		rblist->nr_entries = 0; +	} + +	return; +} + +void rblist__delete(struct rblist *rblist) +{ +	if (rblist != NULL) { +		struct rb_node *pos, *next = rb_first(&rblist->entries); + +		while (next) { +			pos = next; +			next = rb_next(pos); +			rblist__remove_node(rblist, pos); +		} +		free(rblist); +	} +} + +struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx) +{ +	struct rb_node *node; + +	for (node = rb_first(&rblist->entries); node; node = rb_next(node)) { +		if (!idx--) +			return node; +	} + +	return NULL; +}  | 
