/** * @brief Remove an item from the list. * * @param haystack the list to remove the item from * @param needle the data member of the item we're removing * @param fn the comparison function for searching * @param data output parameter containing data of the removed item * * @return the resultant list */ alpm_list_t SYMEXPORT *alpm_list_remove(alpm_list_t *haystack, const void *needle, alpm_list_fn_cmp fn, void **data) { alpm_list_t *i = haystack; if(data) { *data = NULL; } if(needle == NULL) { return haystack; } while(i) { if(i->data == NULL) { i = i->next; continue; } if(fn(i->data, needle) == 0) { haystack = alpm_list_remove_item(haystack, i); if(data) { *data = i->data; } free(i); break; } else { i = i->next; } } return haystack; }
/* Convert a list of alpm_pkg_t * to a graph structure, * with a edge for each dependency. * Returns a list of vertices (one vertex = one package) * (used by alpm_sortbydeps) */ static alpm_list_t *dep_graph_init(alpm_handle_t *handle, alpm_list_t *targets, alpm_list_t *ignore) { alpm_list_t *i, *j; alpm_list_t *vertices = NULL; alpm_list_t *localpkgs = alpm_list_diff( alpm_db_get_pkgcache(handle->db_local), ignore, ptr_cmp); /* We create the vertices */ for(i = targets; i; i = i->next) { alpm_graph_t *vertex = _alpm_graph_new(); vertex->data = (void *)i->data; vertices = alpm_list_add(vertices, vertex); } /* We compute the edges */ for(i = vertices; i; i = i->next) { alpm_graph_t *vertex_i = i->data; alpm_pkg_t *p_i = vertex_i->data; /* TODO this should be somehow combined with alpm_checkdeps */ for(j = vertices; j; j = j->next) { alpm_graph_t *vertex_j = j->data; alpm_pkg_t *p_j = vertex_j->data; if(_alpm_pkg_depends_on(p_i, p_j)) { vertex_i->children = alpm_list_add(vertex_i->children, vertex_j); } } /* lazily add local packages to the dep graph so they don't * get resolved unnecessarily */ j = localpkgs; while(j) { alpm_list_t *next = j->next; if(_alpm_pkg_depends_on(p_i, j->data)) { alpm_graph_t *vertex_j = _alpm_graph_new(); vertex_j->data = (void *)j->data; vertices = alpm_list_add(vertices, vertex_j); vertex_i->children = alpm_list_add(vertex_i->children, vertex_j); localpkgs = alpm_list_remove_item(localpkgs, j); free(j); } j = next; } vertex_i->childptr = vertex_i->children; } alpm_list_free(localpkgs); return vertices; }
/** * @brief Remove a package from a pkghash. * * @param hash the hash to remove the package from * @param pkg the package we are removing * @param data output parameter containing the removed item * * @return the resultant hash */ alpm_pkghash_t *_alpm_pkghash_remove(alpm_pkghash_t *hash, alpm_pkg_t *pkg, alpm_pkg_t **data) { alpm_list_t *i; unsigned int position; if(data) { *data = NULL; } if(pkg == NULL || hash == NULL) { return hash; } position = pkg->name_hash % hash->buckets; while((i = hash->hash_table[position]) != NULL) { alpm_pkg_t *info = i->data; if(info->name_hash == pkg->name_hash && strcmp(info->name, pkg->name) == 0) { unsigned int stop, prev; /* remove from list and hash */ hash->list = alpm_list_remove_item(hash->list, i); if(data) { *data = info; } hash->hash_table[position] = NULL; free(i); hash->entries -= 1; /* Potentially move entries following removed entry to keep open * addressing collision resolution working. We start by finding the * next null bucket to know how far we have to look. */ stop = position + stride; while(stop >= hash->buckets) { stop -= hash->buckets; } while(hash->hash_table[stop] != NULL && stop != position) { stop += stride; while(stop >= hash->buckets) { stop -= hash->buckets; } } stop = (hash->buckets + stop - stride) % hash->buckets; /* We now search backwards from stop to position. If we find an * item that now hashes to position, we will move it, and then try * to plug the new hole we just opened up, until we finally don't * move anything. */ while((prev = move_one_entry(hash, position, stop)) != position) { position = prev; } return hash; } position += stride; while(position >= hash->buckets) { position -= hash->buckets; } } return hash; }