Refactoring ascii art graph

util/stack: extend stack api with r_stack_size
core/graph: use RStack instead of a custom implementation
util/graph: change implementation to use lists and extend api
core/cmd_debug: avoid free r_graph_get_nodes
core/graph: rename some functions and use typedefs for graph struct
core/graph: use RGraph for the ascii art graph
util/list: add const whenever possible
util/graph: add const on r_graph_get_nodes/neighbours
core/graph,core/cmd_debug: use const
core/graph: clean the code (add comments, use const, remove magic nums)

* use r_graph_node_iter for the current node
* reset graph when reloading nodes
* on callgraph edges printing, nth should be 0
* force seek of current node when reloading nodes
* use graph_foreach_node
* core/graph: remove get_current_node because useless
This commit is contained in:
Riccardo Schirone 2015-06-12 11:08:05 +02:00 committed by pancake
parent 0bc0c5586c
commit b279f282ba
9 changed files with 445 additions and 503 deletions

View file

@ -96,7 +96,7 @@ static void dot_trace_traverse(RCore *core, RTree *t) {
const char *gfont = r_config_get (core->config, "graph.font");
struct dot_trace_ght aux_data;
RTreeVisitor vis = { 0 };
RList *nodes;
const RList *nodes;
RListIter *iter;
RGraphNode *n;
@ -117,7 +117,7 @@ static void dot_trace_traverse(RCore *core, RTree *t) {
" shape=box fontname=\"%s\" fontsize=\"8\"];\n", gfont);
r_list_foreach (nodes, iter, n) {
struct trace_node *tn = (struct trace_node *)n->data;
RList *neighbours = r_graph_get_neighbours (aux_data.graph, n);
const RList *neighbours = r_graph_get_neighbours (aux_data.graph, n);
RListIter *it_n;
RGraphNode *w;
@ -136,7 +136,6 @@ static void dot_trace_traverse(RCore *core, RTree *t) {
}
}
r_cons_printf ("}\n");
r_list_free (nodes);
r_graph_free (aux_data.graph);
sdb_free (aux_data.graphnodes);

File diff suppressed because it is too large Load diff

View file

@ -64,8 +64,8 @@ R_API int r_list_set_n(RList *list, int n, void *p);
R_API void *r_list_iter_get_data(RListIter *list);
R_API RListIter *r_list_append(RList *list, void *data);
R_API RListIter *r_list_prepend(RList *list, void *data);
R_API int r_list_length(RList *list);
R_API void* r_list_first(RList *list);
R_API int r_list_length(const RList *list);
R_API void* r_list_first(const RList *list);
R_API RListIter *r_list_add_sorted(RList *list, void *data, RListComparator cmp);
R_API void r_list_sort(RList *list, RListComparator cmp);
@ -79,20 +79,20 @@ R_API RListIter *r_list_item_new (void *data);
R_API void r_list_split (RList *list, void *ptr);
R_API void r_list_split_iter (RList *list, RListIter *iter);
R_API int r_list_join (RList *list1, RList *list2);
R_API void *r_list_get_n (RList *list, int n);
R_API void *r_list_get_n (const RList *list, int n);
R_API int r_list_del_n (RList *list, int n);
R_API void *r_list_get_top (RList *list);
R_API void *r_list_get_bottom (RList *list);
R_API void *r_list_get_top (const RList *list);
R_API void *r_list_get_bottom (const RList *list);
R_API void *r_list_pop (RList *list);
R_API void r_list_reverse (RList *list);
R_API RList *r_list_clone (RList *list);
/* hashlike api */
R_API void *r_list_get_by_int(RList *list, int off, int n);
R_API void *r_list_get_by_int64(RList *list, int off, ut64 n);
R_API void *r_list_get_by_string(RList *list, int off, const char *str);
R_API RListIter *r_list_contains (RList *list, void *p);
R_API RListIter *r_list_find (RList *list, void *p, RListComparator cmp);
R_API void *r_list_get_by_int(const RList *list, int off, int n);
R_API void *r_list_get_by_int64(const RList *list, int off, ut64 n);
R_API void *r_list_get_by_string(const RList *list, int off, const char *str);
R_API RListIter *r_list_contains (const RList *list, void *p);
R_API RListIter *r_list_find (const RList *list, void *p, RListComparator cmp);
/* rlistflist */
// TODO: rename to init or so.. #define r_oflist_new() R_NEW(ROFList);memset

View file

@ -261,10 +261,10 @@ typedef struct r_graph_node_t {
typedef struct r_graph_t {
unsigned int n_nodes;
unsigned int capacity;
unsigned int n_edges;
int last_index;
RGraphNode **nodes;
RList **adjacency;
RList *nodes; /* RGraphNode */
RList *adjacency;
} RGraph;
#ifdef R_API
@ -273,6 +273,7 @@ R_API void r_stack_free (RStack *s);
R_API int r_stack_push (RStack *s, void *el);
R_API void *r_stack_pop (RStack *s);
R_API int r_stack_is_empty (RStack *s);
R_API unsigned int r_stack_size (RStack *s);
R_API RQueue *r_queue_new (int n);
R_API void r_queue_free (RQueue *q);
@ -288,13 +289,15 @@ R_API void r_tree_dfs (RTree *t, RTreeVisitor *vis);
R_API void r_tree_bfs (RTree *t, RTreeVisitor *vis);
R_API RGraphNode *r_graph_get_node (RGraph *g, unsigned int idx);
R_API RList *r_graph_get_nodes (RGraph *g);
R_API RListIter *r_graph_node_iter (RGraph *g, unsigned int idx);
R_API const RList *r_graph_get_nodes (RGraph *g);
R_API RGraph *r_graph_new (void);
R_API void r_graph_free (RGraph* g);
R_API void r_graph_reset (RGraph *g);
R_API RGraphNode *r_graph_add_node (RGraph *g, void *data);
R_API void r_graph_add_edge (RGraph *g, RGraphNode *from, RGraphNode *to);
R_API RList *r_graph_get_neighbours (RGraph *g, RGraphNode *n);
R_API const RList *r_graph_get_neighbours (RGraph *g, RGraphNode *n);
R_API RGraphNode *r_graph_nth_neighbour (RGraph *g, RGraphNode *n, int nth);
R_API int r_graph_adjacent (RGraph *g, RGraphNode *from, RGraphNode *to);
R_API int r_file_is_abspath(const char *file);

View file

@ -2,14 +2,10 @@
#include <r_util.h>
#define INITIAL_CAPACITY 16
/* TODO: allow deletion of nodes and update the "is_in_range"
* function to "is_valid_index" function, that checks if
* the node really exists */
static int is_in_range (RGraph *g, unsigned int idx) {
return idx < g->n_nodes;
}
struct adjacency_t {
unsigned int idx;
RList *adj;
};
static RGraphNode *r_graph_node_new (void *data) {
RGraphNode *p = R_NEW0 (RGraphNode);
@ -24,93 +20,102 @@ static void r_graph_node_free (RGraphNode *n) {
free (n);
}
static void adjancency_free (struct adjacency_t *a) {
r_list_free (a->adj);
free (a);
}
static int node_cmp (unsigned int idx, RGraphNode *b) {
return idx == b->idx ? 0 : -1;
}
static int adj_cmp (unsigned int idx, struct adjacency_t *b) {
return idx == b->idx ? 0 : -1;
}
static RList *get_adjacency (RList *l, unsigned int idx) {
RListIter *it = r_list_find (l, (void *)(size_t)idx, (RListComparator)adj_cmp);
if (!it)
return NULL;
struct adjacency_t *a = (struct adjacency_t *)it->data;
return a->adj;
}
R_API RGraph *r_graph_new () {
RGraph *t = R_NEW0 (RGraph);
t->capacity = INITIAL_CAPACITY;
t->nodes = R_NEWS0 (RGraphNode *, t->capacity);
t->adjacency = R_NEWS0 (RList *, t->capacity);
t->nodes = r_list_new ();
t->nodes->free = (RListFree)r_graph_node_free;
t->adjacency = r_list_new ();
t->adjacency->free = (RListFree)adjancency_free;
t->n_nodes = 0;
t->last_index = -1;
t->last_index = 0;
return t;
}
R_API void r_graph_free (RGraph* t) {
unsigned i;
for (i = 0; i < t->capacity; ++i) {
if (t->nodes[i] != NULL) {
r_list_free (t->adjacency[i]);
r_graph_node_free (t->nodes[i]);
}
}
free (t->nodes);
free (t->adjacency);
r_list_free (t->nodes);
r_list_free (t->adjacency);
free (t);
}
R_API RGraphNode *r_graph_get_node (RGraph *t, unsigned int idx) {
return t->nodes[idx];
RListIter *it = r_list_find (t->nodes, (void *)(size_t)idx, (RListComparator)node_cmp);
if (!it)
return NULL;
return (RGraphNode *)it->data;
}
R_API RListIter *r_graph_node_iter (RGraph *t, unsigned int idx) {
return r_list_find (t->nodes, (void *)(size_t)idx, (RListComparator)node_cmp);
}
R_API void r_graph_reset (RGraph *t) {
unsigned i;
r_list_free (t->nodes);
r_list_free (t->adjacency);
for (i = 0; i < t->capacity; ++i) {
if (t->adjacency[i])
r_list_free (t->adjacency[i]);
if (t->nodes[i])
r_graph_node_free (t->nodes[i]);
}
free (t->nodes);
t->capacity = INITIAL_CAPACITY;
t->nodes = R_NEWS0 (RGraphNode *, t->capacity);
t->adjacency = R_NEWS0 (RList *, t->capacity);
t->nodes = r_list_new ();
t->nodes->free = (RListFree)r_graph_node_free;
t->adjacency = r_list_new ();
t->adjacency->free = (RListFree)adjancency_free;
t->n_nodes = 0;
t->n_edges = 0;
t->last_index = 0;
}
R_API RGraphNode *r_graph_add_node (RGraph *t, void *data) {
RGraphNode *n = r_graph_node_new (data);
struct adjacency_t *a = R_NEW (struct adjacency_t);
if (t->n_nodes == t->capacity) {
int new_capacity = t->capacity * 2;
t->adjacency = realloc (t->adjacency, new_capacity * sizeof(RList *));
t->nodes = realloc (t->nodes, new_capacity * sizeof (RGraphNode *));
memset (t->nodes + t->capacity, 0, (new_capacity - t->capacity) * sizeof (RGraphNode *));
t->capacity = new_capacity;
}
n->idx = ++t->last_index;
t->adjacency[n->idx] = r_list_new();
t->adjacency[n->idx]->free = NULL;
t->nodes[n->idx] = n;
n->idx = t->last_index++;
r_list_append (t->nodes, n);
a->idx = n->idx;
a->adj = r_list_new ();
r_list_append (t->adjacency, a);
t->n_nodes++;
return n;
}
R_API void r_graph_add_edge (RGraph *t, RGraphNode *from, RGraphNode *to) {
if (is_in_range(t, from->idx))
r_list_append(t->adjacency[from->idx], to);
RList *a = get_adjacency (t->adjacency, from->idx);
if (!a) return;
r_list_append(a, to);
t->n_edges++;
}
R_API RList *r_graph_get_neighbours (RGraph *g, RGraphNode *n) {
return is_in_range(g, n->idx) ? g->adjacency[n->idx] : NULL;
R_API const RList *r_graph_get_neighbours (RGraph *g, RGraphNode *n) {
return get_adjacency (g->adjacency, n->idx);
}
/* returns a list with all the nodes in the graph
* NOTE: the user should free the list */
R_API RList *r_graph_get_nodes (RGraph *g) {
RList *res;
unsigned int i;
R_API RGraphNode *r_graph_nth_neighbour (RGraph *g, RGraphNode *n, int nth) {
return (RGraphNode *)r_list_get_n (get_adjacency (g->adjacency, n->idx), nth);
}
res = r_list_new ();
res->free = NULL;
for (i = 0; i < g->capacity; ++i)
if (g->nodes[i])
r_list_append (res, g->nodes[i]);
return res;
R_API const RList *r_graph_get_nodes (RGraph *g) {
return g->nodes;
}
R_API int r_graph_adjacent (RGraph *g, RGraphNode *from, RGraphNode *to) {
return r_list_contains (g->adjacency[from->idx], to) ? R_TRUE : R_FALSE;
return r_list_contains (get_adjacency (g->adjacency, from->idx), to) ? R_TRUE : R_FALSE;
}

View file

@ -23,7 +23,7 @@ void *r_list_iter_get_data(RListIter *list) {
return list->data;
}
RListIter *r_list_iterator (RList *list) {
RListIter *r_list_iterator (const RList *list) {
return list? list->head: NULL;
}
@ -35,7 +35,7 @@ RListIter *r_list_get_next (RListIter *list) {
return list ? list->n : NULL;
}
R_API void* r_list_first(RList *list) {
R_API void* r_list_first(const RList *list) {
if (list && list->head) {
return list->head->data;
}
@ -48,7 +48,7 @@ R_API void r_list_init(RList *list) {
list->free = NULL;
}
R_API int r_list_length(RList *list) {
R_API int r_list_length(const RList *list) {
int count = 0;
RListIter *iter = r_list_iterator (list);
while (iter) {
@ -246,12 +246,12 @@ R_API int r_list_del_n(RList *list, int n) {
return R_FALSE;
}
R_API void *r_list_get_top(RList *list) {
R_API void *r_list_get_top(const RList *list) {
if (list && list->tail)
return list->tail->data;
return NULL;
}
R_API void *r_list_get_bottom(RList *list) {
R_API void *r_list_get_bottom(const RList *list) {
if (list && list->head)
return list->head->data;
return NULL;
@ -335,7 +335,7 @@ R_API int r_list_set_n(RList *list, int n, void *p) {
return R_FALSE;
}
R_API void *r_list_get_n(RList *list, int n) {
R_API void *r_list_get_n(const RList *list, int n) {
RListIter *it;
int i;
if (list)
@ -345,7 +345,7 @@ R_API void *r_list_get_n(RList *list, int n) {
return NULL;
}
R_API void *r_list_get_by_int(RList *list, int off, int n) {
R_API void *r_list_get_by_int(const RList *list, int off, int n) {
ut8 *p;
RListIter *iter;
r_list_foreach (list, iter, p) {
@ -355,7 +355,7 @@ R_API void *r_list_get_by_int(RList *list, int off, int n) {
return NULL;
}
R_API void *r_list_get_by_int64(RList *list, int off, ut64 n) {
R_API void *r_list_get_by_int64(const RList *list, int off, ut64 n) {
ut8 *p;
RListIter *iter;
r_list_foreach (list, iter, p) {
@ -365,7 +365,7 @@ R_API void *r_list_get_by_int64(RList *list, int off, ut64 n) {
return NULL;
}
R_API void *r_list_get_by_string(RList *list, int off, const char *str) {
R_API void *r_list_get_by_string(const RList *list, int off, const char *str) {
char *p;
RListIter *iter;
r_list_foreach (list, iter, p) {
@ -376,7 +376,7 @@ R_API void *r_list_get_by_string(RList *list, int off, const char *str) {
return NULL;
}
R_API RListIter *r_list_contains (RList *list, void *p) {
R_API RListIter *r_list_contains (const RList *list, void *p) {
void *q;
RListIter *iter;
r_list_foreach (list, iter, q) {
@ -386,7 +386,7 @@ R_API RListIter *r_list_contains (RList *list, void *p) {
return NULL;
}
R_API RListIter *r_list_find (RList *list, void *p, RListComparator cmp) {
R_API RListIter *r_list_find (const RList *list, void *p, RListComparator cmp) {
void *q;
RListIter *iter;
r_list_foreach (list, iter, q) {

View file

@ -45,3 +45,7 @@ R_API void *r_stack_pop (RStack *s) {
R_API int r_stack_is_empty (RStack *s) {
return s->top == -1;
}
R_API unsigned int r_stack_size (RStack *s) {
return (unsigned int)(s->top + 1);
}

View file

@ -79,7 +79,6 @@ int main(int argc, char **argv) {
check(g->n_nodes, 10, "n_nodes.again");
check_list(nodes, exp_nodes, "get_all_nodes");
r_list_free(exp_nodes);
r_list_free(nodes);
r_graph_free (g);
return 0;

View file

@ -1,10 +1,11 @@
#include <r_util.h>
void check (int n, int exp) {
void check (int n, int exp, char *descr) {
descr = descr == NULL ? "" : descr;
if (n == exp) {
printf("[+] test passed (actual: %d; expected: %d)\n", n, exp);
printf("[+][%s] test passed (actual: %d; expected: %d)\n", descr, n, exp);
} else {
printf("[-] test failed (actual: %d; expected: %d)\n", n, exp);
printf("[-][%s] test failed (actual: %d; expected: %d)\n", descr, n, exp);
}
}
@ -20,9 +21,11 @@ int main(int argc, char **argv) {
RStack *s = r_stack_new(5);
int n;
check(r_stack_size(s), 0, "stack.0");
r_stack_push(s, (void *)10);
r_stack_push(s, (void *)1);
r_stack_push(s, (void *)2);
check(r_stack_size(s), 3, "stack.3");
r_stack_push(s, (void *)3);
r_stack_push(s, (void *)4);
r_stack_push(s, (void *)5);
@ -31,32 +34,36 @@ int main(int argc, char **argv) {
r_stack_push(s, (void *)9);
r_stack_push(s, (void *)6);
n = (int)r_stack_pop(s);
check(n, 6);
check(n, 6, NULL);
n = (int)r_stack_pop(s);
check(n, 9);
check(n, 9, NULL);
n = (int)r_stack_pop(s);
check(n, 8);
check(n, 8, NULL);
n = (int)r_stack_pop(s);
check(n, 6);
check(n, 6, NULL);
n = (int)r_stack_pop(s);
check(n, 5);
check(n, 5, NULL);
n = (int)r_stack_pop(s);
check(n, 4);
check(n, 4, NULL);
n = (int)r_stack_pop(s);
check(n, 3);
check(n, 3, NULL);
n = (int)r_stack_pop(s);
check(n, 2);
n = (int)r_stack_pop(s);
check(n, 1);
check_empty(s, R_FALSE);
n = (int)r_stack_pop(s);
check(n, 10);
check(n, 2, NULL);
check(r_stack_size(s), 2, "stack.2");
n = (int)r_stack_pop(s);
check(n, 1, NULL);
check_empty(s, R_FALSE);
check(r_stack_size(s), 1, "stack.1");
n = (int)r_stack_pop(s);
check(n, 10, NULL);
check(r_stack_size(s), 0, "stack.0.2");
check_empty(s, R_TRUE);
n = (int)r_stack_pop(s);
check(n, 0);
check(n, 0, NULL);
n = (int)r_stack_pop(s);
check(n, 0);
check(n, 0, NULL);
check_empty(s, R_TRUE);
r_stack_push(s, (void *)10);