2022-01-11 22:05:02 +00:00
|
|
|
/* radare - LGPL - Copyright 2007-2022 - pancake, alvarofe */
|
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"
|
2022-01-11 22:05:02 +00:00
|
|
|
#include <set.h>
|
2012-06-07 01:41:21 +00:00
|
|
|
|
2021-05-19 21:48:40 +00:00
|
|
|
#define MERGE_LIMIT 24
|
|
|
|
|
2021-04-16 15:57:13 +00:00
|
|
|
R_API size_t r_list_iter_length(RListIter *iter) {
|
|
|
|
size_t count = 0;
|
|
|
|
while (iter->n) {
|
|
|
|
count++;
|
|
|
|
iter = iter->n;
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2020-06-14 14:08:32 +00:00
|
|
|
inline RListIter *r_list_iter_new(void) {
|
2016-10-06 00:40:26 +00:00
|
|
|
return calloc (1, sizeof (RListIter));
|
2012-06-07 01:41:21 +00:00
|
|
|
}
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API void r_list_iter_free(RListIter *list) {
|
2012-09-17 15:49:23 +00:00
|
|
|
/* do nothing? */
|
|
|
|
}
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API RListIter *r_list_iter_get_next(RListIter *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->n;
|
2012-06-07 01:41:21 +00:00
|
|
|
}
|
2014-05-02 14:54:27 +00:00
|
|
|
|
2021-06-07 20:30:58 +00:00
|
|
|
R_API RListIter *r_list_iter_get_prev(RListIter *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->p;
|
|
|
|
}
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API void *r_list_iter_get_data(RListIter *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->data;
|
2012-06-07 01:41:21 +00:00
|
|
|
}
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API RListIter *r_list_iterator(const RList *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->head;
|
2012-06-07 01:41:21 +00:00
|
|
|
}
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API RListIter *r_list_push(RList *list, void *item) {
|
2012-06-07 01:41:21 +00:00
|
|
|
return r_list_append (list, item);
|
|
|
|
}
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API RListIter *r_list_get_next(RListIter *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->n;
|
2012-06-07 01:41:21 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 15:08:54 +00:00
|
|
|
// rename to head/last
|
2018-10-01 13:33:30 +00:00
|
|
|
R_API void *r_list_first(const RList *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->head ? list->head->data : NULL;
|
2015-03-22 23:32:31 +00:00
|
|
|
}
|
|
|
|
|
2019-01-07 15:08:54 +00:00
|
|
|
R_API void *r_list_last(const RList *list) {
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
return list->tail ? list->tail->data : NULL;
|
|
|
|
}
|
|
|
|
|
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;
|
2016-10-05 13:59:41 +00:00
|
|
|
list->length = 0;
|
2016-10-24 23:12:06 +00:00
|
|
|
list->sorted = false;
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
|
|
|
|
2015-06-12 09:08:05 +00:00
|
|
|
R_API int r_list_length(const RList *list) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list, 0);
|
|
|
|
return list->length;
|
2010-05-21 15:35:05 +00:00
|
|
|
}
|
|
|
|
|
2014-05-02 14:54:27 +00:00
|
|
|
/* remove all elements of a list */
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API void r_list_purge(RList *list) {
|
2021-01-18 10:14:29 +00:00
|
|
|
if (!list) {
|
|
|
|
return;
|
|
|
|
}
|
2019-08-25 20:43:34 +00:00
|
|
|
RListIter *it = list->head;
|
2018-10-01 13:33:30 +00:00
|
|
|
while (it) {
|
|
|
|
RListIter *next = it->n;
|
|
|
|
r_list_delete (list, it);
|
|
|
|
it = next;
|
2014-05-02 14:54:27 +00:00
|
|
|
}
|
2019-10-03 05:49:20 +00:00
|
|
|
list->length = 0;
|
2018-10-01 13:33:30 +00:00
|
|
|
list->head = list->tail = NULL;
|
2014-05-02 14:54:27 +00:00
|
|
|
}
|
|
|
|
|
2014-05-02 16:29:00 +00:00
|
|
|
/* free the list */
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API void r_list_free(RList *list) {
|
2014-05-02 14:54:27 +00:00
|
|
|
if (list) {
|
|
|
|
r_list_purge (list);
|
2019-11-07 14:40:59 +00:00
|
|
|
free (list);
|
2014-05-02 14:54:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API bool r_list_delete_data(RList *list, void *ptr) {
|
2014-05-02 14:54:27 +00:00
|
|
|
void *p;
|
|
|
|
RListIter *iter;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, false);
|
|
|
|
|
2014-05-02 14:54:27 +00:00
|
|
|
r_list_foreach (list, iter, p) {
|
|
|
|
if (ptr == p) {
|
2017-11-28 15:52:33 +00:00
|
|
|
r_list_delete (list, iter);
|
2016-04-03 23:59:30 +00:00
|
|
|
return true;
|
2014-05-02 14:54:27 +00:00
|
|
|
}
|
|
|
|
}
|
2016-04-03 23:59:30 +00:00
|
|
|
return false;
|
2014-05-02 14:54:27 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API void r_list_delete(RList *list, RListIter *iter) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_if_fail (list && iter);
|
|
|
|
r_list_split_iter (list, iter);
|
|
|
|
if (list->free && iter->data) {
|
|
|
|
list->free (iter->data);
|
2015-04-08 21:06:25 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
iter->data = NULL;
|
2019-11-08 11:38:21 +00:00
|
|
|
free (iter);
|
2014-05-02 14:54:27 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API void r_list_split(RList *list, void *ptr) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_if_fail (list);
|
|
|
|
|
2019-08-25 20:43:34 +00:00
|
|
|
RListIter *iter = r_list_iterator (list);
|
2018-10-01 13:33:30 +00:00
|
|
|
while (iter) {
|
|
|
|
void *item = iter->data;
|
|
|
|
if (ptr == item) {
|
|
|
|
r_list_split_iter (list, iter);
|
|
|
|
free (iter);
|
|
|
|
break;
|
2010-02-27 14:56:07 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
iter = iter->n;
|
2010-02-27 14:56:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API void r_list_split_iter(RList *list, RListIter *iter) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_if_fail (list);
|
|
|
|
|
2016-10-05 13:59:41 +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;
|
|
|
|
}
|
|
|
|
list->length--;
|
2011-03-17 18:05:39 +00:00
|
|
|
}
|
|
|
|
|
2011-04-24 11:46:28 +00:00
|
|
|
//Warning: free functions must be compatible
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API int r_list_join(RList *list1, RList *list2) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list1 && list2, 0);
|
|
|
|
|
2016-11-16 14:24:08 +00:00
|
|
|
if (!(list2->length)) {
|
2015-01-21 12:33:52 +00:00
|
|
|
return 0;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2016-11-16 14:24:08 +00:00
|
|
|
if (!(list1->length)) {
|
2015-06-01 17:42:47 +00:00
|
|
|
list1->head = list2->head;
|
|
|
|
list1->tail = list2->tail;
|
2016-11-16 14:24:08 +00:00
|
|
|
} else {
|
2011-04-24 11:46:28 +00:00
|
|
|
list1->tail->n = list2->head;
|
|
|
|
list2->head->p = list1->tail;
|
2016-11-16 14:24:08 +00:00
|
|
|
list1->tail = list2->tail;
|
|
|
|
list1->tail->n = NULL;
|
|
|
|
list1->sorted = false;
|
2011-04-24 11:46:28 +00:00
|
|
|
}
|
2016-10-05 13:59:41 +00:00
|
|
|
list1->length += list2->length;
|
2019-10-03 05:49:20 +00:00
|
|
|
list2->length = 0;
|
2015-01-18 01:49:19 +00:00
|
|
|
list2->head = list2->tail = NULL;
|
2015-01-21 12:33:52 +00:00
|
|
|
return 1;
|
2011-04-24 11:46:28 +00:00
|
|
|
}
|
|
|
|
|
2020-06-14 14:08:32 +00:00
|
|
|
R_API RList *r_list_new(void) {
|
2016-10-05 13:59:41 +00:00
|
|
|
RList *list = R_NEW0 (RList);
|
|
|
|
if (!list) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-01-14 11:13:48 +00:00
|
|
|
r_list_init (list);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2012-12-13 17:32:26 +00:00
|
|
|
R_API RList *r_list_newf(RListFree f) {
|
2012-12-09 00:39:27 +00:00
|
|
|
RList *l = r_list_new ();
|
2016-10-05 13:59:41 +00:00
|
|
|
if (l) {
|
|
|
|
l->free = f;
|
|
|
|
}
|
2012-12-09 00:39:27 +00:00
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API RListIter *r_list_item_new(void *data) {
|
2016-10-06 00:40:26 +00:00
|
|
|
RListIter *item = R_NEW0 (RListIter);
|
2019-03-03 22:41:19 +00:00
|
|
|
if (item) {
|
|
|
|
item->data = data;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
|
|
|
return item;
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
|
|
|
|
2011-03-23 19:35:40 +00:00
|
|
|
R_API RListIter *r_list_append(RList *list, void *data) {
|
2020-09-05 17:04:41 +00:00
|
|
|
r_return_val_if_fail (list, NULL);
|
2018-10-01 13:33:30 +00:00
|
|
|
|
2021-06-03 18:32:10 +00:00
|
|
|
RListIter *item = r_list_item_new (data);
|
2018-10-01 13:33:30 +00:00
|
|
|
if (!item) {
|
2021-06-03 18:32:10 +00:00
|
|
|
return NULL;
|
2018-10-01 13:33:30 +00:00
|
|
|
}
|
|
|
|
if (list->tail) {
|
|
|
|
list->tail->n = item;
|
|
|
|
}
|
|
|
|
item->p = list->tail;
|
|
|
|
list->tail = item;
|
|
|
|
if (!list->head) {
|
|
|
|
list->head = item;
|
2010-02-04 12:23:53 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
list->length++;
|
|
|
|
list->sorted = false;
|
2016-10-05 13:59:41 +00:00
|
|
|
return item;
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
|
|
|
|
2011-03-23 19:35:40 +00:00
|
|
|
R_API RListIter *r_list_prepend(RList *list, void *data) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
2021-06-03 18:32:10 +00:00
|
|
|
RListIter *item = r_list_item_new (data);
|
2018-10-01 13:33:30 +00:00
|
|
|
if (!item) {
|
|
|
|
return NULL;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
if (list->head) {
|
|
|
|
list->head->p = item;
|
|
|
|
}
|
|
|
|
item->n = list->head;
|
|
|
|
list->head = item;
|
|
|
|
if (!list->tail) {
|
|
|
|
list->tail = item;
|
|
|
|
}
|
|
|
|
list->length++;
|
2021-06-03 18:32:10 +00:00
|
|
|
list->sorted = false;
|
2018-10-01 13:33:30 +00:00
|
|
|
return item;
|
2010-01-14 11:13:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-03 18:32:10 +00:00
|
|
|
R_API RListIter *r_list_insert(RList *list, ut32 n, void *data) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
|
|
|
if (!list->head || !n) {
|
|
|
|
return r_list_prepend (list, data);
|
|
|
|
}
|
2021-06-03 18:32:10 +00:00
|
|
|
|
|
|
|
RListIter *it;
|
|
|
|
ut32 i;
|
2018-10-01 13:33:30 +00:00
|
|
|
for (it = list->head, i = 0; it && it->data; it = it->n, i++) {
|
|
|
|
if (i == n) {
|
2021-06-03 18:32:10 +00:00
|
|
|
RListIter *item = r_list_item_new (data);
|
2018-10-01 13:33:30 +00:00
|
|
|
if (!item) {
|
|
|
|
return NULL;
|
2015-07-13 12:18:28 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
item->n = it;
|
|
|
|
item->p = it->p;
|
|
|
|
if (it->p) {
|
|
|
|
it->p->n = item;
|
|
|
|
}
|
|
|
|
it->p = item;
|
|
|
|
list->length++;
|
2021-06-03 19:45:53 +00:00
|
|
|
list->sorted = false;
|
2018-10-01 13:33:30 +00:00
|
|
|
return item;
|
2015-07-13 12:18:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return r_list_append (list, data);
|
|
|
|
}
|
|
|
|
|
2011-03-10 23:09:35 +00:00
|
|
|
R_API void *r_list_pop(RList *list) {
|
|
|
|
void *data = NULL;
|
|
|
|
RListIter *iter;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
|
|
|
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;
|
2011-03-10 23:09:35 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
data = iter->data;
|
|
|
|
free (iter);
|
2021-01-08 22:33:54 +00:00
|
|
|
list->length--;
|
2011-03-10 23:09:35 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
return data;
|
2011-03-10 23:09:35 +00:00
|
|
|
}
|
|
|
|
|
2015-11-23 23:58:03 +00:00
|
|
|
R_API void *r_list_pop_head(RList *list) {
|
|
|
|
void *data = NULL;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
|
|
|
if (list->head) {
|
2019-08-25 20:43:34 +00:00
|
|
|
RListIter *iter = list->head;
|
2018-10-01 13:33:30 +00:00
|
|
|
if (list->head == list->tail) {
|
|
|
|
list->head = list->tail = NULL;
|
|
|
|
} else {
|
|
|
|
list->head = iter->n;
|
|
|
|
list->head->p = NULL;
|
2015-11-23 23:58:03 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
data = iter->data;
|
|
|
|
free (iter);
|
2021-01-08 22:33:54 +00:00
|
|
|
list->length--;
|
2015-11-23 23:58:03 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
return data;
|
2015-11-23 23:58:03 +00:00
|
|
|
}
|
|
|
|
|
2011-03-12 14:04:48 +00:00
|
|
|
R_API int r_list_del_n(RList *list, int n) {
|
|
|
|
RListIter *it;
|
|
|
|
int i;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, false);
|
|
|
|
|
2018-09-13 08:17:26 +00:00
|
|
|
for (it = list->head, i = 0; it && it->data; it = it->n, i++) {
|
2011-05-21 19:05:21 +00:00
|
|
|
if (i == n) {
|
2016-09-19 12:44:47 +00:00
|
|
|
if (!it->p && !it->n) {
|
2011-05-21 19:05:21 +00:00
|
|
|
list->head = list->tail = NULL;
|
2016-09-19 12:44:47 +00:00
|
|
|
} else if (!it->p) {
|
2011-05-21 19:05:21 +00:00
|
|
|
it->n->p = NULL;
|
|
|
|
list->head = it->n;
|
2016-09-19 12:44:47 +00:00
|
|
|
} else if (!it->n) {
|
2011-05-21 19:05:21 +00:00
|
|
|
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);
|
2016-10-05 13:59:41 +00:00
|
|
|
list->length--;
|
2016-07-12 20:15:19 +00:00
|
|
|
return true;
|
2011-05-21 19:05:21 +00:00
|
|
|
}
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2016-07-12 20:15:19 +00:00
|
|
|
return false;
|
2011-03-12 14:04:48 +00:00
|
|
|
}
|
|
|
|
|
2015-06-12 09:08:05 +00:00
|
|
|
R_API void *r_list_get_top(const RList *list) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
|
|
|
return list->tail ? list->tail->data : NULL;
|
2011-03-12 14:04:48 +00:00
|
|
|
}
|
2015-11-23 23:58:03 +00:00
|
|
|
|
2015-06-12 09:08:05 +00:00
|
|
|
R_API void *r_list_get_bottom(const RList *list) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
|
|
|
return list->head ? list->head->data : NULL;
|
2014-08-23 05:23:55 +00:00
|
|
|
}
|
2011-03-12 14:04:48 +00:00
|
|
|
|
2021-06-03 18:32:10 +00:00
|
|
|
// Moves an iter to the top(tail) of the list
|
|
|
|
// There is an underlying assumption here, that iter is an RListIter of this RList
|
|
|
|
R_API void r_list_iter_to_top(RList *list, RListIter *iter) {
|
|
|
|
r_return_if_fail (list && iter);
|
|
|
|
if (list->tail == iter) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
iter->n->p = iter->p;
|
|
|
|
if (list->head == iter) {
|
|
|
|
list->head = iter->n;
|
|
|
|
} else {
|
|
|
|
iter->p->n = iter->n;
|
|
|
|
}
|
|
|
|
iter->p = list->tail;
|
|
|
|
list->tail->n = iter;
|
|
|
|
iter->n = NULL;
|
|
|
|
list->tail = iter;
|
|
|
|
list->sorted = false;
|
|
|
|
}
|
|
|
|
|
2011-03-12 14:04:48 +00:00
|
|
|
R_API void r_list_reverse(RList *list) {
|
|
|
|
RListIter *it, *tmp;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_if_fail (list);
|
|
|
|
|
|
|
|
for (it = list->head; it && it->data; it = it->p) {
|
|
|
|
tmp = it->p;
|
|
|
|
it->p = it->n;
|
|
|
|
it->n = tmp;
|
2011-03-12 14:04:48 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
tmp = list->head;
|
|
|
|
list->head = list->tail;
|
|
|
|
list->tail = tmp;
|
2011-03-12 14:04:48 +00:00
|
|
|
}
|
|
|
|
|
2020-01-15 09:58:30 +00:00
|
|
|
R_API RList *r_list_clone(const RList *list) {
|
2011-03-12 14:04:48 +00:00
|
|
|
RListIter *iter;
|
|
|
|
void *data;
|
|
|
|
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
2020-06-14 14:08:32 +00:00
|
|
|
RList *l = r_list_new ();
|
2018-10-01 13:33:30 +00:00
|
|
|
if (!l) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
l->free = NULL;
|
|
|
|
r_list_foreach (list, iter, data) {
|
|
|
|
r_list_append (l, data);
|
2011-03-12 14:04:48 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
l->sorted = list->sorted;
|
2011-03-12 14:04:48 +00:00
|
|
|
return l;
|
|
|
|
}
|
|
|
|
|
2014-05-05 10:48:57 +00:00
|
|
|
R_API RListIter *r_list_add_sorted(RList *list, void *data, RListComparator cmp) {
|
2016-10-05 13:59:41 +00:00
|
|
|
RListIter *it, *item = NULL;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list && data && cmp, NULL);
|
|
|
|
|
|
|
|
for (it = list->head; it && it->data && cmp (data, it->data) > 0; it = it->n) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
if (it) {
|
|
|
|
item = R_NEW0 (RListIter);
|
|
|
|
if (!item) {
|
|
|
|
return NULL;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
item->n = it;
|
|
|
|
item->p = it->p;
|
|
|
|
item->data = data;
|
|
|
|
item->n->p = item;
|
|
|
|
if (!item->p) {
|
|
|
|
list->head = item;
|
2014-05-08 15:38:29 +00:00
|
|
|
} else {
|
2018-10-01 13:33:30 +00:00
|
|
|
item->p->n = item;
|
2014-05-08 15:38:29 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
list->length++;
|
|
|
|
} else {
|
|
|
|
r_list_append (list, data);
|
2014-05-08 15:38:29 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
list->sorted = true;
|
|
|
|
return item;
|
2010-07-21 23:14:13 +00:00
|
|
|
}
|
|
|
|
|
2013-10-20 00:09:03 +00:00
|
|
|
R_API int r_list_set_n(RList *list, int n, void *p) {
|
|
|
|
RListIter *it;
|
|
|
|
int i;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, false);
|
2020-01-16 22:23:08 +00:00
|
|
|
for (it = list->head, i = 0; it ; it = it->n, i++) {
|
2018-10-01 13:33:30 +00:00
|
|
|
if (i == n) {
|
|
|
|
if (list->free) {
|
|
|
|
list->free (it->data);
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2018-10-01 13:33:30 +00:00
|
|
|
it->data = p;
|
|
|
|
list->sorted = false;
|
|
|
|
return true;
|
2013-10-20 00:09:03 +00:00
|
|
|
}
|
|
|
|
}
|
2016-07-12 20:15:19 +00:00
|
|
|
return false;
|
2013-10-20 00:09:03 +00:00
|
|
|
}
|
|
|
|
|
2015-06-12 09:08:05 +00:00
|
|
|
R_API void *r_list_get_n(const RList *list, int n) {
|
2010-07-17 16:35:47 +00:00
|
|
|
RListIter *it;
|
|
|
|
int i;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
|
|
|
for (it = list->head, i = 0; it && it->data; it = it->n, i++) {
|
|
|
|
if (i == n) {
|
|
|
|
return it->data;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
|
|
|
}
|
2010-07-17 16:35:47 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API RListIter *r_list_contains(const RList *list, const void *p) {
|
2011-03-23 19:35:40 +00:00
|
|
|
void *q;
|
|
|
|
RListIter *iter;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
2011-03-23 19:35:40 +00:00
|
|
|
r_list_foreach (list, iter, q) {
|
2016-10-05 13:59:41 +00:00
|
|
|
if (p == q) {
|
2011-11-25 03:32:32 +00:00
|
|
|
return iter;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
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
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
R_API RListIter *r_list_find(const RList *list, const void *p, RListComparator cmp) {
|
2013-11-24 00:44:00 +00:00
|
|
|
void *q;
|
|
|
|
RListIter *iter;
|
2018-10-01 13:33:30 +00:00
|
|
|
|
|
|
|
r_return_val_if_fail (list, NULL);
|
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
r_list_foreach (list, iter, q) {
|
2016-10-05 13:59:41 +00:00
|
|
|
if (!cmp (p, q)) {
|
2013-11-24 00:44:00 +00:00
|
|
|
return iter;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2013-11-24 00:44:00 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-10-05 13:59:41 +00:00
|
|
|
static RListIter *_merge(RListIter *first, RListIter *second, RListComparator cmp) {
|
2017-03-26 22:37:18 +00:00
|
|
|
RListIter *next = NULL, *result = NULL, *head = NULL;
|
|
|
|
while (first || second) {
|
|
|
|
if (!second) {
|
|
|
|
next = first;
|
|
|
|
first = first->n;
|
|
|
|
} else if (!first) {
|
|
|
|
next = second;
|
|
|
|
second = second->n;
|
2020-09-09 13:45:34 +00:00
|
|
|
} else if (cmp (first->data, second->data) <= 0) {
|
2017-03-26 22:37:18 +00:00
|
|
|
next = first;
|
|
|
|
first = first->n;
|
|
|
|
} else {
|
|
|
|
next = second;
|
|
|
|
second = second->n;
|
|
|
|
}
|
|
|
|
if (!head) {
|
|
|
|
result = next;
|
|
|
|
head = result;
|
|
|
|
head->p = NULL;
|
|
|
|
} else {
|
|
|
|
result->n = next;
|
|
|
|
next->p = result;
|
|
|
|
result = result->n;
|
|
|
|
}
|
2017-03-26 22:25:32 +00:00
|
|
|
}
|
2017-03-26 22:37:18 +00:00
|
|
|
head->p = NULL;
|
|
|
|
next->n = NULL;
|
|
|
|
return head;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
2021-12-21 18:52:17 +00:00
|
|
|
static RListIter *_r_list_half_split(RListIter *head) {
|
2016-10-05 13:59:41 +00:00
|
|
|
RListIter *tmp;
|
|
|
|
RListIter *fast;
|
|
|
|
RListIter *slow;
|
|
|
|
if (!head || !head->n) {
|
|
|
|
return head;
|
2016-11-16 14:24:08 +00:00
|
|
|
}
|
2016-10-05 13:59:41 +00:00
|
|
|
slow = head;
|
|
|
|
fast = head;
|
2021-05-19 21:48:40 +00:00
|
|
|
int count = 0;
|
2016-10-05 13:59:41 +00:00
|
|
|
while (fast && fast->n && fast->n->n) {
|
|
|
|
fast = fast->n->n;
|
|
|
|
slow = slow->n;
|
2021-05-19 21:48:40 +00:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
if (count < MERGE_LIMIT) {
|
|
|
|
return NULL;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
|
|
|
tmp = slow->n;
|
|
|
|
slow->n = NULL;
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
2021-05-19 21:48:40 +00:00
|
|
|
static void list_insertion_sort_iter(RListIter *iter, RListComparator cmp) {
|
|
|
|
RListIter *it, *it2;
|
|
|
|
for (it = iter; 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-21 18:52:17 +00:00
|
|
|
static RListIter *_merge_sort(RListIter *head, RListComparator cmp) {
|
2016-10-05 13:59:41 +00:00
|
|
|
RListIter *second;
|
|
|
|
if (!head || !head->n) {
|
|
|
|
return head;
|
|
|
|
}
|
|
|
|
second = _r_list_half_split (head);
|
2021-05-19 21:48:40 +00:00
|
|
|
if (second) {
|
|
|
|
head = _merge_sort (head, cmp);
|
|
|
|
second = _merge_sort (second, cmp);
|
|
|
|
return _merge (head, second, cmp);
|
|
|
|
}
|
|
|
|
list_insertion_sort_iter (head, cmp);
|
|
|
|
return head;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
2016-10-05 22:34:52 +00:00
|
|
|
R_API void r_list_merge_sort(RList *list, RListComparator cmp) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_if_fail (list);
|
|
|
|
|
2016-10-29 11:06:11 +00:00
|
|
|
if (!list->sorted && list->head && cmp) {
|
2016-10-26 09:01:42 +00:00
|
|
|
RListIter *iter;
|
2017-03-26 22:37:18 +00:00
|
|
|
list->head = _merge_sort (list->head, cmp);
|
2016-10-26 09:01:42 +00:00
|
|
|
//update tail reference
|
|
|
|
iter = list->head;
|
|
|
|
while (iter && iter->n) {
|
|
|
|
iter = iter->n;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2016-10-26 09:01:42 +00:00
|
|
|
list->tail = iter;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2016-10-26 09:01:42 +00:00
|
|
|
list->sorted = true;
|
2016-10-05 13:59:41 +00:00
|
|
|
}
|
2016-10-05 22:34:52 +00:00
|
|
|
|
|
|
|
R_API void r_list_insertion_sort(RList *list, RListComparator cmp) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_if_fail (list);
|
|
|
|
|
|
|
|
if (!list->sorted) {
|
2016-10-24 23:12:06 +00:00
|
|
|
RListIter *it;
|
|
|
|
RListIter *it2;
|
2016-10-26 09:01:42 +00:00
|
|
|
if (cmp) {
|
2016-10-24 23:12:06 +00:00
|
|
|
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;
|
|
|
|
}
|
2016-10-05 22:34:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-10-24 23:12:06 +00:00
|
|
|
list->sorted = true;
|
2016-10-05 22:34:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//chose wisely based on length
|
|
|
|
R_API void r_list_sort(RList *list, RListComparator cmp) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_return_if_fail (list);
|
2021-05-19 21:48:40 +00:00
|
|
|
if (list->length > MERGE_LIMIT) {
|
2018-10-01 13:33:30 +00:00
|
|
|
r_list_merge_sort (list, cmp);
|
|
|
|
} else {
|
|
|
|
r_list_insertion_sort (list, cmp);
|
2016-10-05 22:34:52 +00:00
|
|
|
}
|
|
|
|
}
|
2016-11-16 14:24:08 +00:00
|
|
|
|
2022-01-11 22:05:02 +00:00
|
|
|
R_API RList *r_list_uniq(const RList *list, RListComparatorItem cmp) {
|
2018-08-09 15:31:12 +00:00
|
|
|
RListIter *iter, *iter2;
|
2022-01-11 22:05:02 +00:00
|
|
|
void *item;
|
|
|
|
int deleted = 0;
|
|
|
|
|
|
|
|
r_return_val_if_fail (list && cmp, 0);
|
|
|
|
RList *rlist = r_list_newf (list->free);
|
|
|
|
SetU *s = set_u_new ();
|
|
|
|
r_list_foreach_safe (list, iter, iter2, item) {
|
|
|
|
ut64 v = cmp (item);
|
|
|
|
if (set_u_contains (s, v)) {
|
|
|
|
deleted ++;
|
|
|
|
} else {
|
|
|
|
set_u_add (s, v);
|
|
|
|
r_list_append (rlist, item);
|
2018-02-12 20:53:35 +00:00
|
|
|
}
|
2022-01-11 22:05:02 +00:00
|
|
|
}
|
|
|
|
set_u_free (s);
|
|
|
|
return rlist;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_list_uniq_inplace(RList *list, RListComparatorItem cmp) {
|
|
|
|
RListIter *iter, *iter2;
|
|
|
|
void *item;
|
|
|
|
int deleted = 0;
|
|
|
|
|
|
|
|
r_return_val_if_fail (list && cmp, 0);
|
|
|
|
SetU *s = set_u_new ();
|
|
|
|
r_list_foreach_safe (list, iter, iter2, item) {
|
|
|
|
ut64 v = cmp (item);
|
|
|
|
if (set_u_contains (s, v)) {
|
|
|
|
r_list_delete (list, iter);
|
|
|
|
deleted ++;
|
|
|
|
} else {
|
|
|
|
set_u_add (s, v);
|
2018-02-12 20:53:35 +00:00
|
|
|
}
|
|
|
|
}
|
2022-01-11 22:05:02 +00:00
|
|
|
set_u_free (s);
|
|
|
|
return deleted;
|
2018-02-12 20:53:35 +00:00
|
|
|
}
|
2019-06-20 11:11:37 +00:00
|
|
|
R_API char *r_list_to_str(RList *list, char ch) {
|
|
|
|
RListIter *iter;
|
|
|
|
RStrBuf *buf = r_strbuf_new ("");
|
|
|
|
if (!buf) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
char *item;
|
|
|
|
r_list_foreach (list, iter, item) {
|
|
|
|
r_strbuf_appendf (buf, "%s%c", item, ch);
|
|
|
|
}
|
|
|
|
return r_strbuf_drain (buf);
|
|
|
|
}
|