Feature #387 ยป 0057-genlist.-ch-Replace-NULLs-with-nullptrs.patch
| utility/genlist.c | ||
|---|---|---|
|
#include "fcthread.h"
|
||
|
#include "log.h"
|
||
|
#include "mem.h"
|
||
|
#include "shared.h" /* array_shuffle */
|
||
|
#include "shared.h" /* array_shuffle() */
|
||
|
#include "genlist.h"
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
struct genlist *genlist_new(void)
|
||
|
{
|
||
|
return genlist_new_full(NULL);
|
||
|
return genlist_new_full(nullptr);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
#ifdef ZERO_VARIABLES_FOR_SEARCHING
|
||
|
pgenlist->nelements = 0;
|
||
|
pgenlist->head_link = NULL;
|
||
|
pgenlist->tail_link = NULL;
|
||
|
pgenlist->head_link = nullptr;
|
||
|
pgenlist->tail_link = nullptr;
|
||
|
#endif /* ZERO_VARIABLES_FOR_SEARCHING */
|
||
|
fc_mutex_init(&pgenlist->mutex);
|
||
|
pgenlist->free_data_func = free_data_func;
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_destroy(struct genlist *pgenlist)
|
||
|
{
|
||
|
if (pgenlist == NULL) {
|
||
|
if (pgenlist == nullptr) {
|
||
|
return;
|
||
|
}
|
||
| ... | ... | |
|
plink->dataptr = dataptr;
|
||
|
plink->prev = prev;
|
||
|
if (NULL != prev) {
|
||
|
if (prev != nullptr) {
|
||
|
prev->next = plink;
|
||
|
} else {
|
||
|
pgenlist->head_link = plink;
|
||
|
}
|
||
|
plink->next = next;
|
||
|
if (NULL != next) {
|
||
|
if (next != nullptr) {
|
||
|
next->prev = plink;
|
||
|
} else {
|
||
|
pgenlist->tail_link = plink;
|
||
| ... | ... | |
|
pgenlist->nelements--;
|
||
|
/* NB: detach the link before calling the free function for avoiding
|
||
|
/* NB: Detach the link before calling the free function for avoiding
|
||
|
* re-entrant code. */
|
||
|
if (NULL != pgenlist->free_data_func) {
|
||
|
if (pgenlist->free_data_func != nullptr) {
|
||
|
pgenlist->free_data_func(plink->dataptr);
|
||
|
}
|
||
|
free(plink);
|
||
| ... | ... | |
|
/************************************************************************//**
|
||
|
Returns a pointer to the genlist link structure at the specified
|
||
|
position. Recall 'pos' -1 refers to the last position.
|
||
|
For pos out of range returns NULL.
|
||
|
For pos out of range returns nullptr.
|
||
|
Traverses list either forwards or backwards for best efficiency.
|
||
|
****************************************************************************/
|
||
|
static struct genlist_link *
|
||
| ... | ... | |
|
} else if (pos == -1) {
|
||
|
return pgenlist->tail_link;
|
||
|
} else if (pos < -1 || pos >= pgenlist->nelements) {
|
||
|
return NULL;
|
||
|
return nullptr;
|
||
|
}
|
||
|
if (pos < pgenlist->nelements / 2) { /* fastest to do forward search */
|
||
|
if (pos < pgenlist->nelements / 2) { /* Fastest to do forward search */
|
||
|
for (plink = pgenlist->head_link; pos != 0; pos--) {
|
||
|
plink = plink->next;
|
||
|
}
|
||
|
} else { /* fastest to do backward search */
|
||
|
} else { /* Fastest to do backward search */
|
||
|
for (plink = pgenlist->tail_link, pos = pgenlist->nelements-pos - 1;
|
||
|
pos != 0; pos--) {
|
||
|
plink = plink->prev;
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
struct genlist *genlist_copy(const struct genlist *pgenlist)
|
||
|
{
|
||
|
return genlist_copy_full(pgenlist, NULL, pgenlist->free_data_func);
|
||
|
return genlist_copy_full(pgenlist, nullptr, pgenlist->free_data_func);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
if (pgenlist) {
|
||
|
struct genlist_link *plink;
|
||
|
if (NULL != copy_data_func) {
|
||
|
if (copy_data_func != nullptr) {
|
||
|
for (plink = pgenlist->head_link; plink; plink = plink->next) {
|
||
|
genlist_link_new(pcopy, copy_data_func(plink->dataptr),
|
||
|
pcopy->tail_link, NULL);
|
||
|
pcopy->tail_link, nullptr);
|
||
|
}
|
||
|
} else {
|
||
|
for (plink = pgenlist->head_link; plink; plink = plink->next) {
|
||
|
genlist_link_new(pcopy, plink->dataptr, pcopy->tail_link, NULL);
|
||
|
genlist_link_new(pcopy, plink->dataptr, pcopy->tail_link, nullptr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
int genlist_size(const struct genlist *pgenlist)
|
||
|
{
|
||
|
fc_assert_ret_val(NULL != pgenlist, 0);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, 0);
|
||
|
return pgenlist->nelements;
|
||
|
}
|
||
|
/************************************************************************//**
|
||
|
Returns the link in the genlist at the position given by 'idx'. For idx
|
||
|
out of range (including an empty list), returns NULL.
|
||
|
out of range (including an empty list), returns nullptr.
|
||
|
Recall 'idx' can be -1 meaning the last element.
|
||
|
****************************************************************************/
|
||
|
struct genlist_link *genlist_link_get(const struct genlist *pgenlist, int idx)
|
||
|
{
|
||
|
fc_assert_ret_val(NULL != pgenlist, NULL);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, nullptr);
|
||
|
return genlist_link_at_pos(pgenlist, idx);
|
||
|
}
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
struct genlist_link *genlist_tail(const struct genlist *pgenlist)
|
||
|
{
|
||
|
return (NULL != pgenlist ? pgenlist->tail_link : NULL);
|
||
|
return (pgenlist != nullptr ? pgenlist->tail_link : nullptr);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
|
Returns the user-data pointer stored in the genlist at the position
|
||
|
given by 'idx'. For idx out of range (including an empty list),
|
||
|
returns NULL.
|
||
|
returns nullptr.
|
||
|
Recall 'idx' can be -1 meaning the last element.
|
||
|
****************************************************************************/
|
||
|
void *genlist_get(const struct genlist *pgenlist, int idx)
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_clear(struct genlist *pgenlist)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
if (0 < pgenlist->nelements) {
|
||
|
genlist_free_fn_t free_data_func = pgenlist->free_data_func;
|
||
|
struct genlist_link *plink = pgenlist->head_link, *plink2;
|
||
|
pgenlist->head_link = NULL;
|
||
|
pgenlist->tail_link = NULL;
|
||
|
pgenlist->head_link = nullptr;
|
||
|
pgenlist->tail_link = nullptr;
|
||
|
pgenlist->nelements = 0;
|
||
|
if (NULL != free_data_func) {
|
||
|
if (free_data_func != nullptr) {
|
||
|
do {
|
||
|
plink2 = plink->next;
|
||
|
free_data_func(plink->dataptr);
|
||
|
free(plink);
|
||
|
} while (NULL != (plink = plink2));
|
||
|
} while ((plink = plink2) != nullptr);
|
||
|
} else {
|
||
|
do {
|
||
|
plink2 = plink->next;
|
||
|
free(plink);
|
||
|
} while (NULL != (plink = plink2));
|
||
|
} while ((plink = plink2) != nullptr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_unique(struct genlist *pgenlist)
|
||
|
{
|
||
|
genlist_unique_full(pgenlist, NULL);
|
||
|
genlist_unique_full(pgenlist, nullptr);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
void genlist_unique_full(struct genlist *pgenlist,
|
||
|
genlist_comp_fn_t comp_data_func)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
if (2 <= pgenlist->nelements) {
|
||
|
struct genlist_link *plink = pgenlist->head_link, *plink2;
|
||
|
if (NULL != comp_data_func) {
|
||
|
if (comp_data_func != nullptr) {
|
||
|
do {
|
||
|
plink2 = plink->next;
|
||
|
if (NULL != plink2 && comp_data_func(plink->dataptr,
|
||
|
plink2->dataptr)) {
|
||
|
if (plink2 != nullptr && comp_data_func(plink->dataptr,
|
||
|
plink2->dataptr)) {
|
||
|
/* Remove this element. */
|
||
|
genlist_link_destroy(pgenlist, plink);
|
||
|
}
|
||
|
} while ((plink = plink2) != NULL);
|
||
|
} while ((plink = plink2) != nullptr);
|
||
|
} else {
|
||
|
do {
|
||
|
plink2 = plink->next;
|
||
|
if (NULL != plink2 && plink->dataptr == plink2->dataptr) {
|
||
|
if (plink2 != nullptr && plink->dataptr == plink2->dataptr) {
|
||
|
/* Remove this element. */
|
||
|
genlist_link_destroy(pgenlist, plink);
|
||
|
}
|
||
|
} while ((plink = plink2) != NULL);
|
||
|
} while ((plink = plink2) != nullptr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
{
|
||
|
struct genlist_link *plink;
|
||
|
fc_assert_ret_val(NULL != pgenlist, FALSE);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, FALSE);
|
||
|
for (plink = pgenlist->head_link; NULL != plink; plink = plink->next) {
|
||
|
for (plink = pgenlist->head_link; plink != nullptr; plink = plink->next) {
|
||
|
if (plink->dataptr == punlink) {
|
||
|
genlist_link_destroy(pgenlist, plink);
|
||
|
return TRUE;
|
||
| ... | ... | |
|
struct genlist_link *plink;
|
||
|
int count = 0;
|
||
|
fc_assert_ret_val(NULL != pgenlist, 0);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, 0);
|
||
|
for (plink = pgenlist->head_link; NULL != plink;) {
|
||
|
for (plink = pgenlist->head_link; plink != nullptr;) {
|
||
|
if (plink->dataptr == punlink) {
|
||
|
struct genlist_link *pnext = plink->next;
|
||
| ... | ... | |
|
bool genlist_remove_if(struct genlist *pgenlist,
|
||
|
genlist_cond_fn_t cond_data_func)
|
||
|
{
|
||
|
fc_assert_ret_val(NULL != pgenlist, FALSE);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, FALSE);
|
||
|
if (NULL != cond_data_func) {
|
||
|
if (cond_data_func != nullptr) {
|
||
|
struct genlist_link *plink = pgenlist->head_link;
|
||
|
for (; NULL != plink; plink = plink->next) {
|
||
|
for (; plink != nullptr; plink = plink->next) {
|
||
|
if (cond_data_func(plink->dataptr)) {
|
||
|
genlist_link_destroy(pgenlist, plink);
|
||
|
return TRUE;
|
||
| ... | ... | |
|
int genlist_remove_all_if(struct genlist *pgenlist,
|
||
|
genlist_cond_fn_t cond_data_func)
|
||
|
{
|
||
|
fc_assert_ret_val(NULL != pgenlist, 0);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, 0);
|
||
|
if (NULL != cond_data_func) {
|
||
|
if (cond_data_func != nullptr) {
|
||
|
struct genlist_link *plink = pgenlist->head_link;
|
||
|
int count = 0;
|
||
|
while (NULL != plink) {
|
||
|
while (plink != nullptr) {
|
||
|
if (cond_data_func(plink->dataptr)) {
|
||
|
struct genlist_link *pnext = plink->next;
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_erase(struct genlist *pgenlist, struct genlist_link *plink)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
if (NULL != plink) {
|
||
|
if (plink != nullptr) {
|
||
|
genlist_link_destroy(pgenlist, plink);
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_pop_front(struct genlist *pgenlist)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
if (NULL != pgenlist->head_link) {
|
||
|
if (pgenlist->head_link != nullptr) {
|
||
|
genlist_link_destroy(pgenlist, pgenlist->head_link);
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_pop_back(struct genlist *pgenlist)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
if (NULL != pgenlist->tail_link) {
|
||
|
if (pgenlist->tail_link != nullptr) {
|
||
|
genlist_link_destroy(pgenlist, pgenlist->tail_link);
|
||
|
}
|
||
|
}
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_insert(struct genlist *pgenlist, void *data, int pos)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
if (0 == pgenlist->nelements) {
|
||
|
/* List is empty, ignore pos. */
|
||
|
genlist_link_new(pgenlist, data, NULL, NULL);
|
||
|
genlist_link_new(pgenlist, data, nullptr, nullptr);
|
||
|
} else if (0 == pos) {
|
||
|
/* Prepend. */
|
||
|
genlist_link_new(pgenlist, data, NULL, pgenlist->head_link);
|
||
|
genlist_link_new(pgenlist, data, nullptr, pgenlist->head_link);
|
||
|
} else if (-1 >= pos || pos >= pgenlist->nelements) {
|
||
|
/* Append. */
|
||
|
genlist_link_new(pgenlist, data, pgenlist->tail_link, NULL);
|
||
|
genlist_link_new(pgenlist, data, pgenlist->tail_link, nullptr);
|
||
|
} else {
|
||
|
/* Insert before plink. */
|
||
|
struct genlist_link *plink = genlist_link_at_pos(pgenlist, pos);
|
||
|
fc_assert_ret(NULL != plink);
|
||
|
fc_assert_ret(plink != nullptr);
|
||
|
genlist_link_new(pgenlist, data, plink->prev, plink);
|
||
|
}
|
||
|
}
|
||
|
/************************************************************************//**
|
||
|
Insert an item after the link. If plink is NULL, prepend to the list.
|
||
|
Insert an item after the link. If plink is nullptr, prepend to the list.
|
||
|
****************************************************************************/
|
||
|
void genlist_insert_after(struct genlist *pgenlist, void *data,
|
||
|
struct genlist_link *plink)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
genlist_link_new(pgenlist, data, plink,
|
||
|
NULL != plink ? plink->next : pgenlist->head_link);
|
||
|
plink != nullptr ? plink->next : pgenlist->head_link);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
void genlist_insert_before(struct genlist *pgenlist, void *data,
|
||
|
struct genlist_link *plink)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
genlist_link_new(pgenlist, data,
|
||
|
NULL != plink ? plink->prev : pgenlist->tail_link, plink);
|
||
|
plink != nullptr ? plink->prev : pgenlist->tail_link, plink);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_prepend(struct genlist *pgenlist, void *data)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
genlist_link_new(pgenlist, data, NULL, pgenlist->head_link);
|
||
|
genlist_link_new(pgenlist, data, nullptr, pgenlist->head_link);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
void genlist_append(struct genlist *pgenlist, void *data)
|
||
|
{
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
genlist_link_new(pgenlist, data, pgenlist->tail_link, NULL);
|
||
|
genlist_link_new(pgenlist, data, pgenlist->tail_link, nullptr);
|
||
|
}
|
||
|
/************************************************************************//**
|
||
|
Return the link where data is equal to 'data'. Returns NULL if not found.
|
||
|
Return the link where data is equal to 'data'. Returns nullptr if not found.
|
||
|
This is an O(n) operation. Hence, "search".
|
||
|
****************************************************************************/
|
||
| ... | ... | |
|
{
|
||
|
struct genlist_link *plink;
|
||
|
fc_assert_ret_val(NULL != pgenlist, NULL);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, nullptr);
|
||
|
for (plink = pgenlist->head_link; plink; plink = plink->next) {
|
||
|
if (plink->dataptr == data) {
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
return nullptr;
|
||
|
}
|
||
|
/************************************************************************//**
|
||
|
Return the link which fit the conditional function. Returns NULL if no
|
||
|
Return the link which fit the conditional function. Returns nullptr if no
|
||
|
match.
|
||
|
****************************************************************************/
|
||
|
struct genlist_link *genlist_search_if(const struct genlist *pgenlist,
|
||
|
genlist_cond_fn_t cond_data_func)
|
||
|
{
|
||
|
fc_assert_ret_val(NULL != pgenlist, NULL);
|
||
|
fc_assert_ret_val(pgenlist != nullptr, nullptr);
|
||
|
if (NULL != cond_data_func) {
|
||
|
if (cond_data_func != nullptr) {
|
||
|
struct genlist_link *plink = pgenlist->head_link;
|
||
|
for (; NULL != plink; plink = plink->next) {
|
||
|
for (; plink != nullptr; plink = plink->next) {
|
||
|
if (cond_data_func(plink->dataptr)) {
|
||
|
return plink;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return NULL;
|
||
|
return nullptr;
|
||
|
}
|
||
|
/************************************************************************//**
|
||
| ... | ... | |
|
struct genlist_link *head, *tail;
|
||
|
int counter;
|
||
|
fc_assert_ret(NULL != pgenlist);
|
||
|
fc_assert_ret(pgenlist != nullptr);
|
||
|
head = pgenlist->head_link;
|
||
|
tail = pgenlist->tail_link;
|
||
|
for (counter = pgenlist->nelements / 2; 0 < counter; counter--) {
|
||
|
/* Swap. */
|
||
|
void *temp = head->dataptr;
|
||
|
head->dataptr = tail->dataptr;
|
||
|
tail->dataptr = temp;
|
||
| utility/genlist.h | ||
|---|---|---|
|
struct genlist_link *genlist_link_get(const struct genlist *pgenlist, int idx);
|
||
|
inline static struct genlist_link *genlist_head(const struct genlist *pgenlist)
|
||
|
{
|
||
|
return (NULL != pgenlist ? pgenlist->head_link : NULL);
|
||
|
return (pgenlist != nullptr ? pgenlist->head_link : nullptr);
|
||
|
}
|
||
|
struct genlist_link *genlist_tail(const struct genlist *pgenlist);
|
||
| ... | ... | |
|
****************************************************************************/
|
||
|
static inline void *genlist_link_data(const struct genlist_link *plink)
|
||
|
{
|
||
|
return (NULL != plink ? plink->dataptr : NULL);
|
||
|
return (plink != nullptr ? plink->dataptr : nullptr);
|
||
|
}
|
||
|
/************************************************************************//**
|
||