radare2/libr/util/spaces.c
Riccardo Schirone 54d5cc3ae0
Rewrite RSpaces to use RBTree and remove use of indices everywhere (#12904)
* Rewrite RSpaces to use RBTree and remove use of indixes everywhere
* Use RSpace in r_meta_space_unset_for
* Use r_str_ndup instead of strndup because windows does not support it
* Add some comments
2019-01-28 16:41:42 +01:00

186 lines
3.8 KiB
C

/* radare - LGPL - Copyright 2019 - pancake, ret2libc */
#include "r_util/r_spaces.h"
R_API RSpaces *r_spaces_new(const char *name) {
RSpaces *sp = R_NEW0 (RSpaces);
if (!sp || !r_spaces_init (sp, name)) {
return NULL;
}
return sp;
}
R_API bool r_spaces_init(RSpaces *sp, const char *name) {
r_return_val_if_fail (sp && name, false);
sp->name = strdup (name);
if (!sp->name) {
goto fail;
}
sp->spaces = NULL;
sp->current = NULL;
sp->spacestack = r_list_new ();
if (!sp->spacestack) {
goto fail;
}
sp->event = r_event_new (sp);
if (!sp->event) {
goto fail;
}
return true;
fail:
r_spaces_free (sp);
return false;
}
R_API void r_spaces_free(RSpaces *sp) {
r_spaces_fini (sp);
free (sp);
}
static void space_free(RSpace *s) {
if (s) {
free (s->name);
free (s);
}
}
static void space_node_free(RBNode *n) {
RSpace *s = container_of (n, RSpace, rb);
space_free (s);
}
R_API void r_spaces_fini(RSpaces *sp) {
r_list_free (sp->spacestack);
sp->spacestack = NULL;
r_rbtree_free (sp->spaces, space_node_free);
sp->spaces = NULL;
r_event_free (sp->event);
sp->event = NULL;
R_FREE (sp->name);
}
static int name_space_cmp(const void *incoming, const RBNode *rb) {
const RSpace *s = container_of (rb, const RSpace, rb);
return strcmp (incoming, s->name);
}
R_API RSpace *r_spaces_get(RSpaces *sp, const char *name) {
RBNode *n = r_rbtree_find (sp->spaces, (void *)name, name_space_cmp);
return n? container_of (n, RSpace, rb): NULL;
}
static int space_cmp(const void *incoming, const RBNode *rb) {
const RSpace *a = (const RSpace *)incoming;
const RSpace *b = container_of (rb, const RSpace, rb);
return strcmp (a->name, b->name);
}
R_API RSpace *r_spaces_add(RSpaces *sp, const char *name) {
r_return_val_if_fail (sp, NULL);
if (!name || !*name || *name == '*') {
return NULL;
}
RSpace *s = r_spaces_get (sp, name);
if (s) {
return s;
}
s = R_NEW0 (RSpace);
if (!s) {
return NULL;
}
s->name = strdup (name);
if (!s->name) {
free (s);
return NULL;
}
r_rbtree_insert (&sp->spaces, s, &s->rb, space_cmp);
return s;
}
R_API RSpace *r_spaces_set(RSpaces *sp, const char *name) {
sp->current = r_spaces_add (sp, name);
return sp->current;
}
R_API bool r_spaces_unset(RSpaces *sp, const char *name) {
RSpace *space = r_spaces_get (sp, name);
if (!space) {
return false;
}
RSpaceEvent ev = { .data.unset.space = space };
r_event_send (sp->event, R_SPACE_EVENT_UNSET, &ev);
return r_rbtree_delete (&sp->spaces, (void *)name, name_space_cmp, space_node_free);
}
R_API int r_spaces_count(RSpaces *sp, const char *name) {
RSpace *s = r_spaces_get (sp, name);
if (!s) {
return 0;
}
RSpaceEvent ev = { .data.count.space = s, .res = 0 };
r_event_send (sp->event, R_SPACE_EVENT_COUNT, &ev);
return ev.res;
}
R_API bool r_spaces_push(RSpaces *sp, const char *name) {
r_return_val_if_fail (sp, false);
r_list_push (sp->spacestack, sp->current? sp->current->name: "*");
r_spaces_set (sp, name);
return true;
}
R_API bool r_spaces_pop(RSpaces *sp) {
char *name = r_list_pop (sp->spacestack);
if (!name) {
return false;
}
RSpace *s = r_spaces_get (sp, name);
r_spaces_set (sp, s? s->name: NULL);
return true;
}
R_API bool r_spaces_rename(RSpaces *sp, const char *oname, const char *nname) {
if (!oname && !sp->current) {
return false;
}
RSpace *s;
if (oname) {
s = r_spaces_get (sp, oname);
if (!s) {
return false;
}
} else {
s = sp->current;
}
RSpace *sn = r_spaces_get (sp, nname);
if (sn) {
return false;
}
RSpaceEvent ev = {
.data.rename.oldname = s->name,
.data.rename.newname = nname,
.data.rename.space = s
};
r_event_send (sp->event, R_SPACE_EVENT_RENAME, &ev);
r_rbtree_delete (&sp->spaces, (void *)s->name, name_space_cmp, NULL);
free (s->name);
s->name = strdup (nname);
r_rbtree_insert (&sp->spaces, s, &s->rb, space_cmp);
return true;
}