2007-01-19 09:28:44 +00:00
|
|
|
/*
|
|
|
|
* alpm_list.c
|
2007-11-16 20:18:45 -06:00
|
|
|
*
|
2020-02-10 10:46:03 +10:00
|
|
|
* Copyright (c) 2006-2020 Pacman Development Team <pacman-dev@archlinux.org>
|
2009-07-01 02:08:33 -05:00
|
|
|
* Copyright (c) 2002-2006 by Judd Vinet <jvinet@zeroflux.org>
|
2007-11-16 20:18:45 -06:00
|
|
|
*
|
2007-01-19 09:28:44 +00:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2007-12-10 22:55:22 -06:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2007-01-19 09:28:44 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
2013-06-03 14:15:31 +10:00
|
|
|
/* Note: alpm_list.{c,h} are intended to be standalone files. Do not include
|
|
|
|
* any other libalpm headers.
|
|
|
|
*/
|
|
|
|
|
2007-03-05 22:13:33 +00:00
|
|
|
/* libalpm */
|
2007-01-19 09:28:44 +00:00
|
|
|
#include "alpm_list.h"
|
2008-02-24 18:07:44 -06:00
|
|
|
|
|
|
|
/* check exported library symbols with: nm -C -D <lib> */
|
|
|
|
#define SYMEXPORT __attribute__((visibility("default")))
|
|
|
|
#define SYMHIDDEN __attribute__((visibility("internal")))
|
2007-01-19 09:28:44 +00:00
|
|
|
|
|
|
|
/* Allocation */
|
|
|
|
|
2007-01-30 07:47:19 +00:00
|
|
|
void SYMEXPORT alpm_list_free(alpm_list_t *list)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
|
|
|
alpm_list_t *it = list;
|
|
|
|
|
|
|
|
while(it) {
|
2007-01-24 08:51:50 +00:00
|
|
|
alpm_list_t *tmp = it->next;
|
|
|
|
free(it);
|
|
|
|
it = tmp;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-01-30 07:47:19 +00:00
|
|
|
void SYMEXPORT alpm_list_free_inner(alpm_list_t *list, alpm_list_fn_free fn)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2007-01-24 08:51:50 +00:00
|
|
|
alpm_list_t *it = list;
|
|
|
|
|
2013-10-10 17:25:22 +02:00
|
|
|
if(fn) {
|
|
|
|
while(it) {
|
|
|
|
if(it->data) {
|
|
|
|
fn(it->data);
|
|
|
|
}
|
|
|
|
it = it->next;
|
2007-01-24 08:51:50 +00:00
|
|
|
}
|
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2007-01-24 08:51:50 +00:00
|
|
|
|
2007-01-19 09:28:44 +00:00
|
|
|
/* Mutators */
|
|
|
|
|
2007-01-30 07:47:19 +00:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_add(alpm_list_t *list, void *data)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2016-01-11 09:29:22 -05:00
|
|
|
alpm_list_append(&list, data);
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
alpm_list_t SYMEXPORT *alpm_list_append(alpm_list_t **list, void *data)
|
|
|
|
{
|
|
|
|
alpm_list_t *ptr;
|
2007-01-19 09:28:44 +00:00
|
|
|
|
2011-09-27 16:14:17 -05:00
|
|
|
ptr = malloc(sizeof(alpm_list_t));
|
2007-01-19 09:28:44 +00:00
|
|
|
if(ptr == NULL) {
|
2016-01-11 09:29:22 -05:00
|
|
|
return NULL;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2008-02-23 22:31:20 +01:00
|
|
|
ptr->data = data;
|
|
|
|
ptr->next = NULL;
|
|
|
|
|
|
|
|
/* Special case: the input list is empty */
|
2016-01-11 09:29:22 -05:00
|
|
|
if(*list == NULL) {
|
|
|
|
*list = ptr;
|
2008-02-23 22:31:20 +01:00
|
|
|
ptr->prev = ptr;
|
2016-01-11 09:29:22 -05:00
|
|
|
} else {
|
|
|
|
alpm_list_t *lp = alpm_list_last(*list);
|
|
|
|
lp->next = ptr;
|
|
|
|
ptr->prev = lp;
|
|
|
|
(*list)->prev = ptr;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2016-01-11 09:29:22 -05:00
|
|
|
return ptr;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2017-02-18 17:09:49 -05:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_append_strdup(alpm_list_t **list, const char *data)
|
|
|
|
{
|
|
|
|
alpm_list_t *ret;
|
|
|
|
char *dup;
|
|
|
|
if((dup = strdup(data)) && (ret = alpm_list_append(list, dup))) {
|
|
|
|
return ret;
|
|
|
|
} else {
|
|
|
|
free(dup);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-19 00:22:02 +02:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_add_sorted(alpm_list_t *list, void *data, alpm_list_fn_cmp fn)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2008-02-23 22:31:20 +01:00
|
|
|
if(!fn || !list) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return alpm_list_add(list, data);
|
2007-01-19 09:28:44 +00:00
|
|
|
} else {
|
|
|
|
alpm_list_t *add = NULL, *prev = NULL, *next = list;
|
|
|
|
|
2011-09-27 16:14:17 -05:00
|
|
|
add = malloc(sizeof(alpm_list_t));
|
2008-02-23 22:31:20 +01:00
|
|
|
if(add == NULL) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return list;
|
2008-02-23 22:31:20 +01:00
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
add->data = data;
|
|
|
|
|
|
|
|
/* Find insertion point. */
|
|
|
|
while(next) {
|
|
|
|
if(fn(add->data, next->data) <= 0) break;
|
|
|
|
prev = next;
|
|
|
|
next = next->next;
|
|
|
|
}
|
|
|
|
|
2008-02-23 22:31:20 +01:00
|
|
|
/* Insert the add node to the list */
|
|
|
|
if(prev == NULL) { /* special case: we insert add as the first element */
|
|
|
|
add->prev = list->prev; /* list != NULL */
|
|
|
|
add->next = list;
|
2007-11-06 00:55:45 -06:00
|
|
|
list->prev = add;
|
2011-03-20 19:45:57 -05:00
|
|
|
return add;
|
2008-02-23 22:31:20 +01:00
|
|
|
} else if(next == NULL) { /* another special case: add last element */
|
|
|
|
add->prev = prev;
|
|
|
|
add->next = NULL;
|
|
|
|
prev->next = add;
|
|
|
|
list->prev = add;
|
2011-03-20 19:45:57 -05:00
|
|
|
return list;
|
2008-02-23 22:31:20 +01:00
|
|
|
} else {
|
|
|
|
add->prev = prev;
|
|
|
|
add->next = next;
|
|
|
|
next->prev = add;
|
|
|
|
prev->next = add;
|
2011-03-20 19:45:57 -05:00
|
|
|
return list;
|
2007-11-06 00:55:45 -06:00
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-11-20 09:11:40 +01:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_join(alpm_list_t *first, alpm_list_t *second)
|
|
|
|
{
|
|
|
|
alpm_list_t *tmp;
|
|
|
|
|
2011-04-20 19:45:16 -05:00
|
|
|
if(first == NULL) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return second;
|
2007-11-20 09:11:40 +01:00
|
|
|
}
|
2011-04-20 19:45:16 -05:00
|
|
|
if(second == NULL) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return first;
|
2007-11-20 09:11:40 +01:00
|
|
|
}
|
|
|
|
/* tmp is the last element of the first list */
|
|
|
|
tmp = first->prev;
|
|
|
|
/* link the first list to the second */
|
|
|
|
tmp->next = second;
|
|
|
|
/* link the second list to the first */
|
|
|
|
first->prev = second->prev;
|
|
|
|
/* set the back reference to the tail */
|
|
|
|
second->prev = tmp;
|
|
|
|
|
2011-03-20 19:45:57 -05:00
|
|
|
return first;
|
2007-11-20 09:11:40 +01:00
|
|
|
}
|
|
|
|
|
2011-12-31 20:25:53 -06:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_mmerge(alpm_list_t *left, alpm_list_t *right,
|
|
|
|
alpm_list_fn_cmp fn)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2011-08-24 17:01:11 +01:00
|
|
|
alpm_list_t *newlist, *lp, *tail_ptr, *left_tail_ptr, *right_tail_ptr;
|
2007-01-19 09:28:44 +00:00
|
|
|
|
2011-08-24 17:01:11 +01:00
|
|
|
if(left == NULL) {
|
2007-01-19 09:28:44 +00:00
|
|
|
return right;
|
2011-08-24 17:01:11 +01:00
|
|
|
}
|
|
|
|
if(right == NULL) {
|
2007-01-19 09:28:44 +00:00
|
|
|
return left;
|
2011-08-24 17:01:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Save tail node pointers for future use */
|
|
|
|
left_tail_ptr = left->prev;
|
|
|
|
right_tail_ptr = right->prev;
|
2007-01-19 09:28:44 +00:00
|
|
|
|
2011-04-20 19:45:16 -05:00
|
|
|
if(fn(left->data, right->data) <= 0) {
|
2007-01-19 09:28:44 +00:00
|
|
|
newlist = left;
|
|
|
|
left = left->next;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
newlist = right;
|
|
|
|
right = right->next;
|
|
|
|
}
|
|
|
|
newlist->prev = NULL;
|
|
|
|
newlist->next = NULL;
|
|
|
|
lp = newlist;
|
|
|
|
|
2011-04-20 19:45:16 -05:00
|
|
|
while((left != NULL) && (right != NULL)) {
|
|
|
|
if(fn(left->data, right->data) <= 0) {
|
2007-01-19 09:28:44 +00:00
|
|
|
lp->next = left;
|
|
|
|
left->prev = lp;
|
|
|
|
left = left->next;
|
2007-11-16 20:18:45 -06:00
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
else {
|
|
|
|
lp->next = right;
|
|
|
|
right->prev = lp;
|
|
|
|
right = right->next;
|
|
|
|
}
|
|
|
|
lp = lp->next;
|
|
|
|
lp->next = NULL;
|
|
|
|
}
|
2011-04-20 19:45:16 -05:00
|
|
|
if(left != NULL) {
|
2007-01-19 09:28:44 +00:00
|
|
|
lp->next = left;
|
|
|
|
left->prev = lp;
|
2011-08-24 17:01:11 +01:00
|
|
|
tail_ptr = left_tail_ptr;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
2011-04-20 19:45:16 -05:00
|
|
|
else if(right != NULL) {
|
2007-01-19 09:28:44 +00:00
|
|
|
lp->next = right;
|
|
|
|
right->prev = lp;
|
2011-08-24 17:01:11 +01:00
|
|
|
tail_ptr = right_tail_ptr;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
2011-08-24 17:01:11 +01:00
|
|
|
else {
|
|
|
|
tail_ptr = lp;
|
2007-11-06 00:55:45 -06:00
|
|
|
}
|
2011-08-24 17:01:11 +01:00
|
|
|
|
|
|
|
newlist->prev = tail_ptr;
|
2007-11-06 00:55:45 -06:00
|
|
|
|
2011-03-20 19:45:57 -05:00
|
|
|
return newlist;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2011-12-31 20:25:53 -06:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_msort(alpm_list_t *list, size_t n,
|
|
|
|
alpm_list_fn_cmp fn)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2011-04-20 19:45:16 -05:00
|
|
|
if(n > 1) {
|
2011-12-31 20:25:53 -06:00
|
|
|
size_t half = n / 2;
|
|
|
|
size_t i = half - 1;
|
|
|
|
alpm_list_t *left = list, *lastleft = list, *right;
|
|
|
|
|
|
|
|
while(i--) {
|
|
|
|
lastleft = lastleft->next;
|
|
|
|
}
|
|
|
|
right = lastleft->next;
|
2012-02-01 03:11:47 +10:00
|
|
|
|
|
|
|
/* tidy new lists */
|
2007-11-16 20:18:45 -06:00
|
|
|
lastleft->next = NULL;
|
2012-02-01 03:11:47 +10:00
|
|
|
right->prev = left->prev;
|
|
|
|
left->prev = lastleft;
|
2007-01-19 09:28:44 +00:00
|
|
|
|
2011-12-31 20:25:53 -06:00
|
|
|
left = alpm_list_msort(left, half, fn);
|
|
|
|
right = alpm_list_msort(right, n - half, fn);
|
2007-01-19 09:28:44 +00:00
|
|
|
list = alpm_list_mmerge(left, right, fn);
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return list;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2011-02-02 20:46:28 -06:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_remove_item(alpm_list_t *haystack,
|
|
|
|
alpm_list_t *item)
|
|
|
|
{
|
|
|
|
if(haystack == NULL || item == NULL) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return haystack;
|
2011-02-02 20:46:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if(item == haystack) {
|
|
|
|
/* Special case: removing the head node which has a back reference to
|
|
|
|
* the tail node */
|
|
|
|
haystack = item->next;
|
|
|
|
if(haystack) {
|
|
|
|
haystack->prev = item->prev;
|
|
|
|
}
|
|
|
|
item->prev = NULL;
|
|
|
|
} else if(item == haystack->prev) {
|
|
|
|
/* Special case: removing the tail node, so we need to fix the back
|
|
|
|
* reference on the head node. We also know tail != head. */
|
|
|
|
if(item->prev) {
|
|
|
|
/* i->next should always be null */
|
|
|
|
item->prev->next = item->next;
|
|
|
|
haystack->prev = item->prev;
|
|
|
|
item->prev = NULL;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* Normal case, non-head and non-tail node */
|
|
|
|
if(item->next) {
|
|
|
|
item->next->prev = item->prev;
|
|
|
|
}
|
|
|
|
if(item->prev) {
|
|
|
|
item->prev->next = item->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-20 19:45:57 -05:00
|
|
|
return haystack;
|
2011-02-02 20:46:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack,
|
|
|
|
const void *needle, alpm_list_fn_cmp fn, void **data)
|
2007-11-06 00:55:45 -06:00
|
|
|
{
|
2011-02-02 20:46:28 -06:00
|
|
|
alpm_list_t *i = haystack;
|
2007-01-19 09:28:44 +00:00
|
|
|
|
|
|
|
if(data) {
|
|
|
|
*data = NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-16 15:57:08 +02:00
|
|
|
if(needle == NULL) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return haystack;
|
2008-07-16 15:57:08 +02:00
|
|
|
}
|
|
|
|
|
2007-01-19 09:28:44 +00:00
|
|
|
while(i) {
|
|
|
|
if(i->data == NULL) {
|
2009-10-10 23:57:10 +02:00
|
|
|
i = i->next;
|
2007-01-19 09:28:44 +00:00
|
|
|
continue;
|
|
|
|
}
|
Cleanup usages of alpm_list_find and alpm_list_remove.
* remove obsolete and unused *_cmp helper functions like deppkg_cmp and
_alpm_grp_cmp
* new alpm_list_remove_str function, used 6 times in handle.c
* remove _alpm_prov_cmp / _alpm_db_whatprovides and replace them by
a more general alpm_find_pkg_satisfiers with a cleaner implementation.
before: alpm_db_whatprovides(db, targ)
after: alpm_find_pkg_satisfiers(alpm_db_getpkgcache(db), targ)
* remove satisfycmp and replace alpm_list_find + satisfycmp usage by
_alpm_find_dep_satisfiers.
before : alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)
after : _alpm_find_dep_satisfiers(_alpm_db_get_pkgcache(db), dep)
* remove _alpm_pkgname_pkg_cmp, which was used with alpm_list_remove, and
use _alpm_pkg_find + alpm_list_remove with _alpm_pkg_cmp instead.
This commit actually get rids of all complicated and asymmetric _cmp
functions. I first thought these functions were worth it, be caused it
allowed us to reuse list_find and list_remove. But this was at the detriment
of the clarity and also the ease of use of these functions, dangerous
because of their asymmetricity.
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2008-05-10 18:47:42 +02:00
|
|
|
if(fn(i->data, needle) == 0) {
|
2011-02-02 20:46:28 -06:00
|
|
|
haystack = alpm_list_remove_item(haystack, i);
|
2007-01-19 09:28:44 +00:00
|
|
|
|
|
|
|
if(data) {
|
|
|
|
*data = i->data;
|
|
|
|
}
|
|
|
|
free(i);
|
2011-02-02 20:46:28 -06:00
|
|
|
break;
|
2007-11-06 00:55:45 -06:00
|
|
|
} else {
|
2011-02-02 20:46:28 -06:00
|
|
|
i = i->next;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-20 19:45:57 -05:00
|
|
|
return haystack;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
Cleanup usages of alpm_list_find and alpm_list_remove.
* remove obsolete and unused *_cmp helper functions like deppkg_cmp and
_alpm_grp_cmp
* new alpm_list_remove_str function, used 6 times in handle.c
* remove _alpm_prov_cmp / _alpm_db_whatprovides and replace them by
a more general alpm_find_pkg_satisfiers with a cleaner implementation.
before: alpm_db_whatprovides(db, targ)
after: alpm_find_pkg_satisfiers(alpm_db_getpkgcache(db), targ)
* remove satisfycmp and replace alpm_list_find + satisfycmp usage by
_alpm_find_dep_satisfiers.
before : alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)
after : _alpm_find_dep_satisfiers(_alpm_db_get_pkgcache(db), dep)
* remove _alpm_pkgname_pkg_cmp, which was used with alpm_list_remove, and
use _alpm_pkg_find + alpm_list_remove with _alpm_pkg_cmp instead.
This commit actually get rids of all complicated and asymmetric _cmp
functions. I first thought these functions were worth it, be caused it
allowed us to reuse list_find and list_remove. But this was at the detriment
of the clarity and also the ease of use of these functions, dangerous
because of their asymmetricity.
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2008-05-10 18:47:42 +02:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_remove_str(alpm_list_t *haystack,
|
|
|
|
const char *needle, char **data)
|
|
|
|
{
|
2011-03-20 19:45:57 -05:00
|
|
|
return alpm_list_remove(haystack, (const void *)needle,
|
|
|
|
(alpm_list_fn_cmp)strcmp, (void **)data);
|
Cleanup usages of alpm_list_find and alpm_list_remove.
* remove obsolete and unused *_cmp helper functions like deppkg_cmp and
_alpm_grp_cmp
* new alpm_list_remove_str function, used 6 times in handle.c
* remove _alpm_prov_cmp / _alpm_db_whatprovides and replace them by
a more general alpm_find_pkg_satisfiers with a cleaner implementation.
before: alpm_db_whatprovides(db, targ)
after: alpm_find_pkg_satisfiers(alpm_db_getpkgcache(db), targ)
* remove satisfycmp and replace alpm_list_find + satisfycmp usage by
_alpm_find_dep_satisfiers.
before : alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)
after : _alpm_find_dep_satisfiers(_alpm_db_get_pkgcache(db), dep)
* remove _alpm_pkgname_pkg_cmp, which was used with alpm_list_remove, and
use _alpm_pkg_find + alpm_list_remove with _alpm_pkg_cmp instead.
This commit actually get rids of all complicated and asymmetric _cmp
functions. I first thought these functions were worth it, be caused it
allowed us to reuse list_find and list_remove. But this was at the detriment
of the clarity and also the ease of use of these functions, dangerous
because of their asymmetricity.
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2008-05-10 18:47:42 +02:00
|
|
|
}
|
|
|
|
|
2007-06-05 17:34:33 -04:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_remove_dupes(const alpm_list_t *list)
|
2007-10-31 11:37:49 -05:00
|
|
|
{
|
2007-06-05 17:34:33 -04:00
|
|
|
const alpm_list_t *lp = list;
|
|
|
|
alpm_list_t *newlist = NULL;
|
2007-01-19 09:28:44 +00:00
|
|
|
while(lp) {
|
2007-11-16 20:50:58 +01:00
|
|
|
if(!alpm_list_find_ptr(newlist, lp->data)) {
|
2017-05-10 18:54:55 -04:00
|
|
|
if(alpm_list_append(&newlist, lp->data) == NULL) {
|
|
|
|
alpm_list_free(newlist);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
lp = lp->next;
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return newlist;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2007-07-19 00:22:02 +02:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_strdup(const alpm_list_t *list)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2007-06-05 17:34:33 -04:00
|
|
|
const alpm_list_t *lp = list;
|
|
|
|
alpm_list_t *newlist = NULL;
|
2007-01-19 09:28:44 +00:00
|
|
|
while(lp) {
|
2017-05-10 18:54:55 -04:00
|
|
|
if(alpm_list_append_strdup(&newlist, lp->data) == NULL) {
|
|
|
|
FREELIST(newlist);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
lp = lp->next;
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return newlist;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2007-10-19 13:17:51 -04:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_copy(const alpm_list_t *list)
|
|
|
|
{
|
|
|
|
const alpm_list_t *lp = list;
|
|
|
|
alpm_list_t *newlist = NULL;
|
|
|
|
while(lp) {
|
2017-05-10 18:54:55 -04:00
|
|
|
if(alpm_list_append(&newlist, lp->data) == NULL) {
|
|
|
|
alpm_list_free(newlist);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-19 13:17:51 -04:00
|
|
|
lp = lp->next;
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return newlist;
|
2007-10-19 13:17:51 -04:00
|
|
|
}
|
|
|
|
|
2007-11-14 22:51:16 -06:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_copy_data(const alpm_list_t *list,
|
|
|
|
size_t size)
|
2007-10-29 21:03:41 -05:00
|
|
|
{
|
|
|
|
const alpm_list_t *lp = list;
|
|
|
|
alpm_list_t *newlist = NULL;
|
|
|
|
while(lp) {
|
2011-09-27 16:14:17 -05:00
|
|
|
void *newdata = malloc(size);
|
2007-10-29 21:03:41 -05:00
|
|
|
if(newdata) {
|
2007-11-14 22:51:16 -06:00
|
|
|
memcpy(newdata, lp->data, size);
|
2017-05-10 18:54:55 -04:00
|
|
|
if(alpm_list_append(&newlist, newdata) == NULL) {
|
|
|
|
free(newdata);
|
|
|
|
FREELIST(newlist);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-10-29 21:03:41 -05:00
|
|
|
lp = lp->next;
|
2017-05-10 18:54:55 -04:00
|
|
|
} else {
|
|
|
|
FREELIST(newlist);
|
|
|
|
return NULL;
|
2007-10-29 21:03:41 -05:00
|
|
|
}
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return newlist;
|
2007-10-29 21:03:41 -05:00
|
|
|
}
|
|
|
|
|
2007-07-19 00:22:02 +02:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_reverse(alpm_list_t *list)
|
2007-10-31 11:37:49 -05:00
|
|
|
{
|
|
|
|
const alpm_list_t *lp;
|
2008-02-23 22:31:20 +01:00
|
|
|
alpm_list_t *newlist = NULL, *backup;
|
2007-01-19 09:28:44 +00:00
|
|
|
|
2008-02-23 22:31:20 +01:00
|
|
|
if(list == NULL) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return NULL;
|
2007-11-06 00:55:45 -06:00
|
|
|
}
|
|
|
|
|
2008-02-23 22:31:20 +01:00
|
|
|
lp = alpm_list_last(list);
|
|
|
|
/* break our reverse circular list */
|
|
|
|
backup = list->prev;
|
|
|
|
list->prev = NULL;
|
|
|
|
|
2007-01-19 09:28:44 +00:00
|
|
|
while(lp) {
|
2017-05-10 18:54:55 -04:00
|
|
|
if(alpm_list_append(&newlist, lp->data) == NULL) {
|
|
|
|
alpm_list_free(newlist);
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
lp = lp->prev;
|
|
|
|
}
|
2008-02-23 22:31:20 +01:00
|
|
|
list->prev = backup; /* restore tail pointer */
|
2011-03-20 19:45:57 -05:00
|
|
|
return newlist;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Accessors */
|
|
|
|
|
2010-12-08 15:13:36 +10:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_nth(const alpm_list_t *list, size_t n)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2007-06-05 17:34:33 -04:00
|
|
|
const alpm_list_t *i = list;
|
2007-01-19 09:28:44 +00:00
|
|
|
while(n--) {
|
|
|
|
i = i->next;
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return (alpm_list_t *)i;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2007-06-05 17:34:33 -04:00
|
|
|
inline alpm_list_t SYMEXPORT *alpm_list_next(const alpm_list_t *node)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2008-02-23 22:31:20 +01:00
|
|
|
if(node) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return node->next;
|
2008-02-23 22:31:20 +01:00
|
|
|
} else {
|
2011-03-20 19:45:57 -05:00
|
|
|
return NULL;
|
2008-02-23 22:31:20 +01:00
|
|
|
}
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
2007-03-29 00:40:49 -04:00
|
|
|
|
2011-07-04 11:17:12 +10:00
|
|
|
inline alpm_list_t SYMEXPORT *alpm_list_previous(const alpm_list_t *list)
|
2011-07-03 10:10:36 +10:00
|
|
|
{
|
2011-07-04 11:17:12 +10:00
|
|
|
if(list && list->prev->next) {
|
|
|
|
return list->prev;
|
2011-07-03 10:10:36 +10:00
|
|
|
} else {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-19 00:22:02 +02:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_last(const alpm_list_t *list)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2007-11-06 00:55:45 -06:00
|
|
|
if(list) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return list->prev;
|
2007-11-06 00:55:45 -06:00
|
|
|
} else {
|
2011-03-20 19:45:57 -05:00
|
|
|
return NULL;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Misc */
|
|
|
|
|
2010-12-08 15:13:36 +10:00
|
|
|
size_t SYMEXPORT alpm_list_count(const alpm_list_t *list)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2010-12-08 15:13:36 +10:00
|
|
|
size_t i = 0;
|
2007-01-19 09:28:44 +00:00
|
|
|
const alpm_list_t *lp = list;
|
|
|
|
while(lp) {
|
|
|
|
++i;
|
|
|
|
lp = lp->next;
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return i;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2007-12-02 23:48:12 +01:00
|
|
|
void SYMEXPORT *alpm_list_find(const alpm_list_t *haystack, const void *needle,
|
2007-11-16 20:50:58 +01:00
|
|
|
alpm_list_fn_cmp fn)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2007-06-05 17:34:33 -04:00
|
|
|
const alpm_list_t *lp = haystack;
|
2007-01-19 09:28:44 +00:00
|
|
|
while(lp) {
|
2007-11-16 20:50:58 +01:00
|
|
|
if(lp->data && fn(lp->data, needle) == 0) {
|
2011-03-20 19:45:57 -05:00
|
|
|
return lp->data;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
lp = lp->next;
|
|
|
|
}
|
2011-03-20 19:45:57 -05:00
|
|
|
return NULL;
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2007-11-16 20:50:58 +01:00
|
|
|
/* trivial helper function for alpm_list_find_ptr */
|
Cleanup usages of alpm_list_find and alpm_list_remove.
* remove obsolete and unused *_cmp helper functions like deppkg_cmp and
_alpm_grp_cmp
* new alpm_list_remove_str function, used 6 times in handle.c
* remove _alpm_prov_cmp / _alpm_db_whatprovides and replace them by
a more general alpm_find_pkg_satisfiers with a cleaner implementation.
before: alpm_db_whatprovides(db, targ)
after: alpm_find_pkg_satisfiers(alpm_db_getpkgcache(db), targ)
* remove satisfycmp and replace alpm_list_find + satisfycmp usage by
_alpm_find_dep_satisfiers.
before : alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)
after : _alpm_find_dep_satisfiers(_alpm_db_get_pkgcache(db), dep)
* remove _alpm_pkgname_pkg_cmp, which was used with alpm_list_remove, and
use _alpm_pkg_find + alpm_list_remove with _alpm_pkg_cmp instead.
This commit actually get rids of all complicated and asymmetric _cmp
functions. I first thought these functions were worth it, be caused it
allowed us to reuse list_find and list_remove. But this was at the detriment
of the clarity and also the ease of use of these functions, dangerous
because of their asymmetricity.
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2008-05-10 18:47:42 +02:00
|
|
|
static int ptr_cmp(const void *p, const void *q)
|
2007-11-16 20:50:58 +01:00
|
|
|
{
|
2011-03-20 19:45:57 -05:00
|
|
|
return (p != q);
|
2007-11-16 20:50:58 +01:00
|
|
|
}
|
|
|
|
|
2011-03-20 19:45:57 -05:00
|
|
|
void SYMEXPORT *alpm_list_find_ptr(const alpm_list_t *haystack,
|
|
|
|
const void *needle)
|
2007-11-16 20:50:58 +01:00
|
|
|
{
|
2011-03-20 19:45:57 -05:00
|
|
|
return alpm_list_find(haystack, needle, ptr_cmp);
|
2007-11-16 20:50:58 +01:00
|
|
|
}
|
|
|
|
|
Cleanup usages of alpm_list_find and alpm_list_remove.
* remove obsolete and unused *_cmp helper functions like deppkg_cmp and
_alpm_grp_cmp
* new alpm_list_remove_str function, used 6 times in handle.c
* remove _alpm_prov_cmp / _alpm_db_whatprovides and replace them by
a more general alpm_find_pkg_satisfiers with a cleaner implementation.
before: alpm_db_whatprovides(db, targ)
after: alpm_find_pkg_satisfiers(alpm_db_getpkgcache(db), targ)
* remove satisfycmp and replace alpm_list_find + satisfycmp usage by
_alpm_find_dep_satisfiers.
before : alpm_list_find(_alpm_db_get_pkgcache(db), dep, satisfycmp)
after : _alpm_find_dep_satisfiers(_alpm_db_get_pkgcache(db), dep)
* remove _alpm_pkgname_pkg_cmp, which was used with alpm_list_remove, and
use _alpm_pkg_find + alpm_list_remove with _alpm_pkg_cmp instead.
This commit actually get rids of all complicated and asymmetric _cmp
functions. I first thought these functions were worth it, be caused it
allowed us to reuse list_find and list_remove. But this was at the detriment
of the clarity and also the ease of use of these functions, dangerous
because of their asymmetricity.
Signed-off-by: Chantry Xavier <shiningxc@gmail.com>
Signed-off-by: Dan McGee <dan@archlinux.org>
2008-05-10 18:47:42 +02:00
|
|
|
char SYMEXPORT *alpm_list_find_str(const alpm_list_t *haystack,
|
|
|
|
const char *needle)
|
2007-01-19 09:28:44 +00:00
|
|
|
{
|
2011-03-20 19:45:57 -05:00
|
|
|
return (char *)alpm_list_find(haystack, (const void *)needle,
|
|
|
|
(alpm_list_fn_cmp)strcmp);
|
2007-01-19 09:28:44 +00:00
|
|
|
}
|
|
|
|
|
2010-03-24 15:22:23 +10:00
|
|
|
void SYMEXPORT alpm_list_diff_sorted(const alpm_list_t *left,
|
|
|
|
const alpm_list_t *right, alpm_list_fn_cmp fn,
|
2009-10-11 02:38:33 +02:00
|
|
|
alpm_list_t **onlyleft, alpm_list_t **onlyright)
|
|
|
|
{
|
2010-03-24 15:22:23 +10:00
|
|
|
const alpm_list_t *l = left;
|
|
|
|
const alpm_list_t *r = right;
|
2009-10-11 02:38:33 +02:00
|
|
|
|
|
|
|
if(!onlyleft && !onlyright) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-04-20 19:45:16 -05:00
|
|
|
while(l != NULL && r != NULL) {
|
2009-10-11 02:38:33 +02:00
|
|
|
int cmp = fn(l->data, r->data);
|
|
|
|
if(cmp < 0) {
|
|
|
|
if(onlyleft) {
|
|
|
|
*onlyleft = alpm_list_add(*onlyleft, l->data);
|
|
|
|
}
|
|
|
|
l = l->next;
|
|
|
|
}
|
|
|
|
else if(cmp > 0) {
|
|
|
|
if(onlyright) {
|
|
|
|
*onlyright = alpm_list_add(*onlyright, r->data);
|
|
|
|
}
|
|
|
|
r = r->next;
|
|
|
|
} else {
|
|
|
|
l = l->next;
|
|
|
|
r = r->next;
|
|
|
|
}
|
|
|
|
}
|
2011-04-20 19:45:16 -05:00
|
|
|
while(l != NULL) {
|
2009-10-11 02:38:33 +02:00
|
|
|
if(onlyleft) {
|
|
|
|
*onlyleft = alpm_list_add(*onlyleft, l->data);
|
|
|
|
}
|
|
|
|
l = l->next;
|
|
|
|
}
|
2011-04-20 19:45:16 -05:00
|
|
|
while(r != NULL) {
|
2009-10-11 02:38:33 +02:00
|
|
|
if(onlyright) {
|
|
|
|
*onlyright = alpm_list_add(*onlyright, r->data);
|
|
|
|
}
|
|
|
|
r = r->next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-19 00:22:02 +02:00
|
|
|
alpm_list_t SYMEXPORT *alpm_list_diff(const alpm_list_t *lhs,
|
2007-06-05 17:34:33 -04:00
|
|
|
const alpm_list_t *rhs, alpm_list_fn_cmp fn)
|
2007-03-01 07:03:05 +00:00
|
|
|
{
|
2009-10-11 02:38:33 +02:00
|
|
|
alpm_list_t *left, *right;
|
2007-06-05 17:34:33 -04:00
|
|
|
alpm_list_t *ret = NULL;
|
2007-03-01 07:03:05 +00:00
|
|
|
|
2009-10-11 02:38:33 +02:00
|
|
|
left = alpm_list_copy(lhs);
|
|
|
|
left = alpm_list_msort(left, alpm_list_count(left), fn);
|
|
|
|
right = alpm_list_copy(rhs);
|
|
|
|
right = alpm_list_msort(right, alpm_list_count(right), fn);
|
|
|
|
|
|
|
|
alpm_list_diff_sorted(left, right, fn, &ret, NULL);
|
|
|
|
|
|
|
|
alpm_list_free(left);
|
|
|
|
alpm_list_free(right);
|
2011-03-20 19:45:57 -05:00
|
|
|
return ret;
|
2007-03-01 07:03:05 +00:00
|
|
|
}
|
|
|
|
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 04:47:29 -05:00
|
|
|
void SYMEXPORT *alpm_list_to_array(const alpm_list_t *list, size_t n,
|
|
|
|
size_t size)
|
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
const alpm_list_t *item;
|
|
|
|
char *array;
|
|
|
|
|
|
|
|
if(n == 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2011-09-27 16:14:17 -05:00
|
|
|
array = malloc(n * size);
|
Convert package filelists to an array instead of linked list
This accomplishes quite a few things with one rather invasive change.
1. Iteration is much more performant, due to a reduction in pointer
chasing and linear item access.
2. Data structures are smaller- we no longer have the overhead of the
linked list as the file struts are now laid out consecutively in
memory.
3. Memory allocation has been massively reworked. Before, we would
allocate three different pieces of memory per file item- the list
struct, the file struct, and the copied filename. What this resulted
in was massive fragmentation of memory when loading filelists since
the memory allocator had to leave holes all over the place. The new
situation here now removes the need for any list item allocation;
allocates the file structs in contiguous memory (and reallocs as
necessary), leaving only the strings as individually allocated. Tests
using valgrind (massif) show some pretty significant memory
reductions on the worst case `pacman -Ql > /dev/null` (366387 files
on my machine):
Before:
Peak heap: 54,416,024 B
Useful heap: 36,840,692 B
Extra heap: 17,575,332 B
After:
Peak heap: 38,004,352 B
Useful heap: 28,101,347 B
Extra heap: 9,903,005 B
Several small helper methods have been introduced, including a list to
array conversion helper as well as a filelist merge sort that works
directly on arrays.
Signed-off-by: Dan McGee <dan@archlinux.org>
2011-07-19 04:47:29 -05:00
|
|
|
if(array == NULL) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
for(i = 0, item = list; i < n && item; i++, item = item->next) {
|
|
|
|
memcpy(array + i * size, item->data, size);
|
|
|
|
}
|
|
|
|
return array;
|
|
|
|
}
|