Skip to content

Commit

Permalink
rdlist: add remove_elem() and remove_multi_cmp()
Browse files Browse the repository at this point in the history
  • Loading branch information
edenhill committed Jan 2, 2018
1 parent 4a86230 commit 91872da
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 4 deletions.
28 changes: 24 additions & 4 deletions src/rdlist.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ void *rd_list_add (rd_list_t *rl, void *elem) {
return rl->rl_elems[rl->rl_cnt++];
}

static void rd_list_remove0 (rd_list_t *rl, int idx) {
void rd_list_remove_elem (rd_list_t *rl, int idx) {
rd_assert(idx < rl->rl_cnt);

if (idx + 1 < rl->rl_cnt)
Expand All @@ -126,7 +126,7 @@ void *rd_list_remove (rd_list_t *rl, void *match_elem) {

RD_LIST_FOREACH(elem, rl, i) {
if (elem == match_elem) {
rd_list_remove0(rl, i);
rd_list_remove_elem(rl, i);
return elem;
}
}
Expand All @@ -143,7 +143,7 @@ void *rd_list_remove_cmp (rd_list_t *rl, void *match_elem,
RD_LIST_FOREACH(elem, rl, i) {
if (elem == match_elem ||
!cmp(elem, match_elem)) {
rd_list_remove0(rl, i);
rd_list_remove_elem(rl, i);
return elem;
}
}
Expand All @@ -152,6 +152,26 @@ void *rd_list_remove_cmp (rd_list_t *rl, void *match_elem,
}


int rd_list_remove_multi_cmp (rd_list_t *rl, void *match_elem,
int (*cmp) (void *_a, void *_b)) {

void *elem;
int i;
int cnt = 0;

/* Scan backwards to minimize memmoves */
RD_LIST_FOREACH_REVERSE(elem, rl, i) {
if (match_elem == cmp ||
!cmp(elem, match_elem)) {
rd_list_remove_elem(rl, i);
cnt++;
}
}

return cnt;
}


/**
* Trampoline to avoid the double pointers in callbacks.
*
Expand Down Expand Up @@ -267,7 +287,7 @@ void rd_list_apply (rd_list_t *rl,

RD_LIST_FOREACH(elem, rl, i) {
if (!cb(elem, opaque)) {
rd_list_remove0(rl, i);
rd_list_remove_elem(rl, i);
i--;
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/rdlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,26 @@ void *rd_list_remove (rd_list_t *rl, void *match_elem);
void *rd_list_remove_cmp (rd_list_t *rl, void *match_elem,
int (*cmp) (void *_a, void *_b));


/**
* @brief Remove element at index \p idx.
*
* This is a O(1) + memmove operation
*/
void rd_list_remove_elem (rd_list_t *rl, int idx);


/**
* @brief Remove all elements matching comparator.
*
* @returns the number of elements removed.
*
* @sa rd_list_remove()
*/
int rd_list_remove_multi_cmp (rd_list_t *rl, void *match_elem,
int (*cmp) (void *_a, void *_b));


/**
* Sort list using comparator
*/
Expand Down

0 comments on commit 91872da

Please sign in to comment.