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:
parent
0bc0c5586c
commit
b279f282ba
9 changed files with 445 additions and 503 deletions
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue