2012-12-09 00:39:27 +00:00
|
|
|
/* radare - LGPL - Copyright 2007-2012 - pancake */
|
2011-12-16 15:33:06 +00:00
|
|
|
// TODO: RRef - reference counting
|
2011-03-17 18:05:39 +00:00
|
|
|
|
2012-06-07 01:41:21 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
|
2012-07-20 15:23:24 +00:00
|
|
|
#define _R_LIST_C_
|
|
|
|
#include "r_util.h"
|
2012-06-07 01:41:21 +00:00
|
|
|
|
|
|
|
inline RListIter *r_list_iter_new () {
|
|
|
|
return malloc (sizeof (RListIter));
|
|
|
|
}
|
|
|
|
|
2012-09-17 15:49:23 +00:00
|
|
|
void r_list_iter_free (RListIter *list) {
|
|
|
|
/* do nothing? */
|
|
|
|
}
|
|
|
|
|
2012-06-07 01:41:21 +00:00
|
|
|
RListIter *r_list_iter_get_next(RListIter *list) {
|
|
|
|
return list->n;
|
|
|
|
}
|
|
|
|
void *r_list_iter_get_data(RListIter *list) {
|
|
|
|
return list->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
RListIter *r_list_append(RList *list, void *data);
|
|
|
|
RListIter *r_list_iterator (RList *list) {
|
|
|
|
return list? list->head: NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RListIter *r_list_push (RList *list, void *item) {
|
|
|
|
return r_list_append (list, item);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *r_list_get (RList *list) {
|
|
|
|
printf ("XXX: dynamic r_list_get is broken, use _get_next\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
RListIter *r_list_get_next (RListIter *list) {
|
|
|
|
return list->n;
|
|
|
|
}
|
|
|
|
|
2010-01-14 11:13:48 +00:00
|
|
|
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API void r_list_init(RList *list) {
|
2010-01-14 11:13:48 +00:00
|
|
|
list->head = NULL;
|
|
|
|
list->tail = NULL;
|
|
|
|
list->free = NULL;
|
|
|
|
}
|
|
|
|
|
2010-05-21 15:35:05 +00:00
|
|
|
R_API int r_list_length(RList *list) {
|
|
|
|
int count = 0;
|
|
|
|
RListIter *iter = r_list_iterator (list);
|
|
|
|
while (iter) {
|
|
|
|
count ++;
|
|
|
|
iter = iter->n;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API void r_list_unlink (RList *list, void *ptr) {
|
|
|
|
RListIter *iter = r_list_iterator (list);
|
2010-02-27 14:56:07 +00:00
|
|
|
while (iter) {
|
|
|
|
void *item = iter->data;
|
2010-02-04 12:23:53 +00:00
|
|
|
if (ptr == item) {
|
2010-02-27 14:56:07 +00:00
|
|
|
r_list_delete (list, iter);
|
2010-02-04 12:23:53 +00:00
|
|
|
break;
|
|
|
|
}
|
2010-02-27 14:56:07 +00:00
|
|
|
iter = iter->n;
|
2010-02-04 12:23:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-02-27 14:56:07 +00:00
|
|
|
R_API void r_list_split (RList *list, void *ptr) {
|
|
|
|
RListIter *iter = r_list_iterator (list);
|
|
|
|
while (iter) {
|
|
|
|
void *item = iter->data;
|
|
|
|
if (ptr == item) {
|
|
|
|
r_list_split_iter (list, iter);
|
|
|
|
free (iter);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
iter = iter->n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_list_split_iter (RList *list, RListIter *iter) {
|
2011-03-17 18:05:39 +00:00
|
|
|
if (list->head == iter) list->head = iter->n;
|
|
|
|
if (list->tail == iter) list->tail = iter->p;
|
|
|
|
if (iter->p) iter->p->n = iter->n;
|
|
|
|
if (iter->n) iter->n->p = iter->p;
|
|
|
|
}
|
|
|
|
|
2011-04-24 11:46:28 +00:00
|
|
|
//Warning: free functions must be compatible
|
|
|
|
R_API void r_list_join (RList *list1, RList *list2) {
|
|
|
|
if (list1->tail == NULL) {
|
|
|
|
list1->tail = list2->head;
|
|
|
|
} else if (list2->head != NULL) {
|
|
|
|
list1->tail->n = list2->head;
|
|
|
|
list2->head->p = list1->tail;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-29 11:55:27 +00:00
|
|
|
// XXX r_list_delete_data == r_list_unlink !!!! this is conceptually wrong
|
2011-03-17 18:05:39 +00:00
|
|
|
R_API boolt r_list_delete_data (RList *list, void *ptr) {
|
|
|
|
void *p;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (list, iter, p) {
|
|
|
|
if (ptr == p) {
|
|
|
|
r_list_delete (list, iter);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
2010-02-27 14:56:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_list_delete (RList *list, RListIter *iter) {
|
|
|
|
r_list_split_iter (list, iter);
|
2011-11-25 03:32:32 +00:00
|
|
|
if (list->free && iter->data)
|
2010-02-27 14:56:07 +00:00
|
|
|
list->free (iter->data);
|
2011-11-25 03:32:32 +00:00
|
|
|
iter->data = NULL;
|
2010-02-27 14:56:07 +00:00
|
|
|
free (iter);
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
|
|
|
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API RList *r_list_new() {
|
2010-03-12 12:35:10 +00:00
|
|
|
RList *list = R_NEW (RList);
|
2010-01-14 11:13:48 +00:00
|
|
|
r_list_init (list);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2012-12-09 00:39:27 +00:00
|
|
|
R_API RList *r_list_newf(RListFree *f) {
|
|
|
|
RList *l = r_list_new ();
|
|
|
|
if (l) l->free = f;
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2011-11-30 09:27:01 +00:00
|
|
|
/* remove all elements of a list */
|
|
|
|
R_API void r_list_purge (RList *list) {
|
|
|
|
RListIter *it;
|
|
|
|
if (list) {
|
|
|
|
it = list->head;
|
|
|
|
while (it) {
|
|
|
|
RListIter *next = it->n;
|
|
|
|
r_list_delete (list, it);
|
|
|
|
it = next;
|
|
|
|
// free (it);
|
|
|
|
}
|
|
|
|
list->head = list->tail = NULL;
|
|
|
|
}
|
|
|
|
//free (list);
|
|
|
|
}
|
|
|
|
|
|
|
|
// same as purge.. but without a correct name.. need refactoring
|
|
|
|
// TODO: rename to r_list_purge() or find a better name
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API void r_list_destroy (RList *list) {
|
2011-02-18 09:58:17 +00:00
|
|
|
RListIter *it;
|
|
|
|
if (list) {
|
|
|
|
it = list->head;
|
|
|
|
while (it) {
|
|
|
|
RListIter *next = it->n;
|
|
|
|
r_list_delete (list, it);
|
|
|
|
it = next;
|
2011-03-17 18:05:39 +00:00
|
|
|
// free (it);
|
2011-02-18 09:58:17 +00:00
|
|
|
}
|
|
|
|
list->head = list->tail = NULL;
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
2011-03-17 18:05:39 +00:00
|
|
|
//free (list);
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
|
|
|
|
2010-03-10 12:23:43 +00:00
|
|
|
R_API void r_list_free (RList *list) {
|
2011-05-21 19:05:21 +00:00
|
|
|
if (list) {
|
|
|
|
r_list_destroy (list);
|
|
|
|
free (list);
|
|
|
|
}
|
2010-03-10 12:23:43 +00:00
|
|
|
}
|
|
|
|
|
2010-02-04 12:23:53 +00:00
|
|
|
R_API RListIter *r_list_item_new (void *data) {
|
2010-03-12 12:35:10 +00:00
|
|
|
RListIter *new = R_NEW (RListIter);
|
2010-01-14 11:13:48 +00:00
|
|
|
new->data = data;
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2011-03-23 19:35:40 +00:00
|
|
|
R_API RListIter *r_list_append(RList *list, void *data) {
|
2010-02-04 12:23:53 +00:00
|
|
|
RListIter *new = NULL;
|
2011-11-25 03:32:32 +00:00
|
|
|
if (list && data) {
|
2010-02-04 12:23:53 +00:00
|
|
|
new = R_NEW (RListIter);
|
|
|
|
if (list->tail)
|
2010-02-15 21:59:26 +00:00
|
|
|
list->tail->n = new;
|
2010-02-04 12:23:53 +00:00
|
|
|
new->data = data;
|
2010-02-15 21:59:26 +00:00
|
|
|
new->p = list->tail;
|
|
|
|
new->n = NULL;
|
2010-02-04 12:23:53 +00:00
|
|
|
list->tail = new;
|
|
|
|
if (list->head == NULL)
|
|
|
|
list->head = new;
|
|
|
|
}
|
2010-01-14 11:13:48 +00:00
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2011-03-23 19:35:40 +00:00
|
|
|
R_API RListIter *r_list_prepend(RList *list, void *data) {
|
2010-03-12 12:35:10 +00:00
|
|
|
RListIter *new = R_NEW (RListIter);
|
2010-01-14 11:13:48 +00:00
|
|
|
if (list->head)
|
2010-02-15 21:59:26 +00:00
|
|
|
list->head->p = new;
|
2010-01-14 11:13:48 +00:00
|
|
|
new->data = data;
|
2010-02-15 21:59:26 +00:00
|
|
|
new->n = list->head;
|
|
|
|
new->p = NULL;
|
2010-01-14 11:13:48 +00:00
|
|
|
list->head = new;
|
|
|
|
if (list->tail == NULL)
|
|
|
|
list->tail = new;
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
2011-03-10 23:09:35 +00:00
|
|
|
R_API void *r_list_pop(RList *list) {
|
|
|
|
void *data = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
if (list->tail) {
|
|
|
|
iter = list->tail;
|
|
|
|
if (list->head == list->tail) {
|
|
|
|
list->head = list->tail = NULL;
|
|
|
|
} else {
|
|
|
|
list->tail = iter->p;
|
|
|
|
list->tail->n = NULL;
|
|
|
|
}
|
|
|
|
data = iter->data;
|
|
|
|
free (iter);
|
|
|
|
}
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
|
2011-03-12 14:04:48 +00:00
|
|
|
R_API int r_list_del_n(RList *list, int n) {
|
|
|
|
RListIter *it;
|
|
|
|
int i;
|
|
|
|
|
2011-05-21 19:05:21 +00:00
|
|
|
if (!list)
|
|
|
|
return R_FALSE;
|
|
|
|
for (it = list->head, i = 0; it && it->data; it = it->n, i++)
|
|
|
|
if (i == n) {
|
|
|
|
if (it->p == NULL && it->n == NULL) {
|
|
|
|
list->head = list->tail = NULL;
|
|
|
|
} else if (it->p == NULL) {
|
|
|
|
it->n->p = NULL;
|
|
|
|
list->head = it->n;
|
|
|
|
} else if (it->n == NULL) {
|
|
|
|
it->p->n = NULL;
|
|
|
|
list->tail = it->p;
|
|
|
|
} else {
|
|
|
|
it->p->n = it->n;
|
|
|
|
it->n->p = it->p;
|
2011-03-12 14:04:48 +00:00
|
|
|
}
|
2011-05-21 19:05:21 +00:00
|
|
|
free (it);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2011-03-12 14:04:48 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void *r_list_get_top(RList *list) {
|
|
|
|
if (list && list->tail)
|
|
|
|
return list->tail->data;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_list_reverse(RList *list) {
|
|
|
|
RListIter *it, *tmp;
|
|
|
|
if (list) {
|
|
|
|
for (it = list->head; it && it->data; it = it->p) {
|
|
|
|
tmp = it->p;
|
|
|
|
it->p = it->n;
|
|
|
|
it->n = tmp;
|
|
|
|
}
|
|
|
|
tmp = list->head;
|
|
|
|
list->head = list->tail;
|
|
|
|
list->tail = tmp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RList *r_list_clone (RList *list) {
|
|
|
|
RList *l = NULL;
|
|
|
|
RListIter *iter;
|
|
|
|
void *data;
|
|
|
|
|
|
|
|
if (list) {
|
|
|
|
l = r_list_new ();
|
|
|
|
l->free = NULL;
|
|
|
|
r_list_foreach (list, iter, data)
|
|
|
|
r_list_append (l, data);
|
|
|
|
}
|
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2010-07-21 23:14:13 +00:00
|
|
|
R_API void r_list_sort(RList *list, RListComparator cmp) {
|
|
|
|
RListIter *it;
|
|
|
|
RListIter *it2;
|
|
|
|
for (it = list->head; it && it->data; it = it->n) {
|
|
|
|
for (it2 = it->n; it2 && it2->data; it2 = it2->n) {
|
|
|
|
if (cmp (it->data, it2->data)>0) {
|
|
|
|
void *t = it->data;
|
|
|
|
it->data = it2->data;
|
|
|
|
it2->data = t;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_list_add_sorted(RList *list, void *data, RListComparator cmp) {
|
|
|
|
if (r_list_append (list, data))
|
|
|
|
r_list_sort (list, cmp); // TODO: inefficient
|
|
|
|
}
|
|
|
|
|
2010-07-17 16:35:47 +00:00
|
|
|
R_API void *r_list_get_n(RList *list, int n) {
|
|
|
|
RListIter *it;
|
|
|
|
int i;
|
2010-09-23 18:42:35 +00:00
|
|
|
if (list)
|
2010-07-17 16:35:47 +00:00
|
|
|
for (it = list->head, i = 0; it && it->data; it = it->n, i++)
|
|
|
|
if (i == n)
|
|
|
|
return it->data;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-09-01 18:32:24 +00:00
|
|
|
R_API void *r_list_get_by_int(RList *list, int off, int n) {
|
|
|
|
ut8 *p;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach(list, iter, p) {
|
|
|
|
if (!memcmp (&n, p+off, sizeof (int)))
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void *r_list_get_by_int64(RList *list, int off, ut64 n) {
|
|
|
|
ut8 *p;
|
|
|
|
RListIter *iter;
|
2010-09-24 14:45:56 +00:00
|
|
|
r_list_foreach (list, iter, p) {
|
2010-09-01 18:32:24 +00:00
|
|
|
if (!memcmp (&n, p+off, sizeof (ut64)))
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void *r_list_get_by_string(RList *list, int off, const char *str) {
|
2010-09-24 14:45:56 +00:00
|
|
|
char *p;
|
2010-09-01 18:32:24 +00:00
|
|
|
RListIter *iter;
|
2010-09-24 14:45:56 +00:00
|
|
|
r_list_foreach (list, iter, p) {
|
2010-09-01 18:32:24 +00:00
|
|
|
const char *ptr = p+off;
|
|
|
|
if (!strcmp (str, ptr))
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-11-25 03:32:32 +00:00
|
|
|
R_API RListIter *r_list_contains (RList *list, void *p) {
|
2011-03-23 19:35:40 +00:00
|
|
|
void *q;
|
|
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (list, iter, q) {
|
|
|
|
if (p == q)
|
2011-11-25 03:32:32 +00:00
|
|
|
return iter;
|
2011-03-23 19:35:40 +00:00
|
|
|
}
|
2011-11-25 03:32:32 +00:00
|
|
|
return NULL;
|
2011-03-23 19:35:40 +00:00
|
|
|
}
|
|
|
|
|
2010-01-14 11:13:48 +00:00
|
|
|
#if TEST
|
2010-07-21 23:14:13 +00:00
|
|
|
|
|
|
|
// TODO: move into t/list.c
|
2010-01-14 11:13:48 +00:00
|
|
|
int main () {
|
2010-02-04 12:23:53 +00:00
|
|
|
RListIter *iter, *it;
|
|
|
|
RList *l = r_list_new ();
|
2010-01-14 11:13:48 +00:00
|
|
|
|
|
|
|
r_list_append (l, "foo");
|
|
|
|
r_list_append (l, "bar");
|
|
|
|
r_list_append (l, "cow");
|
|
|
|
r_list_prepend (l, "HEAD");
|
|
|
|
r_list_prepend (l, "HEAD 00");
|
|
|
|
it = r_list_append (l, "LAST");
|
|
|
|
|
2010-09-24 14:45:56 +00:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
r_list_foreach(l, iter, str) {
|
|
|
|
printf("-- %s\n", str);
|
|
|
|
}
|
|
|
|
printf("--**--\n");
|
|
|
|
r_list_foreach_prev(l, iter, str) {
|
|
|
|
printf("-- %s\n", str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-21 23:14:13 +00:00
|
|
|
iter = r_list_iterator (l);
|
|
|
|
while (r_list_iter_next (iter)) {
|
|
|
|
const char *str = r_list_iter_get (iter);
|
|
|
|
printf ("-> %s\n", str);
|
|
|
|
}
|
|
|
|
eprintf ("--sort--\n");
|
|
|
|
r_list_sort (l, (RListComparator)strcmp);
|
|
|
|
iter = r_list_iterator (l);
|
|
|
|
while (r_list_iter_next (iter)) {
|
|
|
|
const char *str = r_list_iter_get (iter);
|
|
|
|
printf ("-> %s\n", str);
|
|
|
|
}
|
|
|
|
|
2010-01-14 11:13:48 +00:00
|
|
|
r_list_delete (l, it);
|
|
|
|
|
2010-07-17 16:35:47 +00:00
|
|
|
char *foo = (char*) r_list_get_n (l, 2);
|
|
|
|
printf (" - n=2 => %s\n", foo);
|
2010-01-14 11:13:48 +00:00
|
|
|
iter = r_list_iterator (l);
|
|
|
|
while (r_list_iter_next (iter)) {
|
2010-02-04 12:23:53 +00:00
|
|
|
RListIter *cur = iter;
|
2010-01-14 11:13:48 +00:00
|
|
|
char *str = r_list_iter_get (iter);
|
|
|
|
if (!strcmp (str, "bar"))
|
|
|
|
r_list_delete (l, cur);
|
|
|
|
}
|
|
|
|
|
|
|
|
iter = r_list_iterator (l);
|
|
|
|
while (r_list_iter_next (iter)) {
|
|
|
|
char *str = r_list_iter_get (iter);
|
2010-01-18 12:45:02 +00:00
|
|
|
//XXX r_list_delete (l, iter);
|
2010-01-14 11:13:48 +00:00
|
|
|
printf (" - %s\n", str);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_list_free (l);
|
|
|
|
|
|
|
|
/* ------------- */
|
|
|
|
l = r_list_new ();
|
2010-03-08 18:40:21 +00:00
|
|
|
l->free = free;
|
2010-01-14 11:13:48 +00:00
|
|
|
|
|
|
|
r_list_append (l, strdup ("one"));
|
|
|
|
r_list_append (l, strdup ("two"));
|
|
|
|
r_list_append (l, strdup ("tri"));
|
|
|
|
it = r_list_append (l, strdup ("LAST"));
|
|
|
|
|
|
|
|
r_list_delete (l, it);
|
|
|
|
|
|
|
|
{
|
2010-02-04 12:23:53 +00:00
|
|
|
RListIter* i = r_list_iterator (l);
|
2010-02-15 21:59:26 +00:00
|
|
|
for (; i; i = i->n) {
|
2010-01-18 12:45:02 +00:00
|
|
|
char *str = i->data;
|
2010-01-14 11:13:48 +00:00
|
|
|
printf (" * %s\n", str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-03-08 18:40:21 +00:00
|
|
|
r_list_free (l);
|
2010-01-14 11:13:48 +00:00
|
|
|
|
2011-03-12 14:04:48 +00:00
|
|
|
l = r_list_new ();
|
|
|
|
l->free = free;
|
|
|
|
|
|
|
|
r_list_append (l, strdup ("one"));
|
|
|
|
r_list_append (l, strdup ("two"));
|
|
|
|
r_list_append (l, strdup ("tri"));
|
|
|
|
|
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
r_list_foreach (l, it, str)
|
|
|
|
printf (" - %s\n", str);
|
|
|
|
|
|
|
|
RList *list;
|
|
|
|
list = r_list_clone (l);
|
|
|
|
|
|
|
|
r_list_foreach (list, it, str)
|
|
|
|
printf (" - %s\n", str);
|
|
|
|
|
|
|
|
r_list_reverse (l);
|
|
|
|
|
|
|
|
r_list_foreach (l, it, str)
|
|
|
|
printf (" * %s\n", str);
|
|
|
|
}
|
|
|
|
|
|
|
|
r_list_free (l);
|
2011-03-17 18:05:39 +00:00
|
|
|
//r_list_free (l);
|
2011-03-12 14:04:48 +00:00
|
|
|
|
2010-01-14 11:13:48 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|