Skip to content

Commit

Permalink
seqset.c: add seqset_remove()
Browse files Browse the repository at this point in the history
  • Loading branch information
ksmurchison committed Nov 18, 2022
1 parent 6c95c13 commit 53f739e
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
31 changes: 31 additions & 0 deletions cunit/seqset.testc
Original file line number Diff line number Diff line change
Expand Up @@ -519,4 +519,35 @@ static void test_simplify(void)
seqset_free(&seq);
}

static void test_remove(void)
{
seqset_t *seq;
char *s;

seq = seqset_parse("1:8,10,12:14,16:20", NULL, 0);
CU_ASSERT_PTR_NOT_NULL_FATAL(seq);

seqset_remove(seq, 18);
s = seqset_cstring(seq);
CU_ASSERT_STRING_EQUAL(s, "1:8,10,12:14,16:17,19:20");
free(s);

seqset_remove(seq, 1);
s = seqset_cstring(seq);
CU_ASSERT_STRING_EQUAL(s, "2:8,10,12:14,16:17,19:20");
free(s);

seqset_remove(seq, 14);
s = seqset_cstring(seq);
CU_ASSERT_STRING_EQUAL(s, "2:8,10,12:13,16:17,19:20");
free(s);

seqset_remove(seq, 10);
s = seqset_cstring(seq);
CU_ASSERT_STRING_EQUAL(s, "2:8,12:13,16:17,19:20");
free(s);

seqset_free(&seq);
}

/* vim: set ft=c: */
43 changes: 41 additions & 2 deletions lib/seqset.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ struct seq_range {
unsigned high;
};

#define RANGE_SIZE sizeof(struct seq_range)

struct seqset {
struct seq_range *set;
size_t len;
Expand Down Expand Up @@ -128,8 +130,7 @@ EXPORTED void seqset_add(seqset_t *seq, unsigned num, int ismember)
if (!seq->set || seq->set[seq->len-1].high < seq->prev || num <= seq->prev) {
if (seq->len == seq->alloc) {
seq->alloc += SETGROWSIZE;
seq->set =
xrealloc(seq->set, seq->alloc * sizeof(struct seq_range));
seq->set = xrealloc(seq->set, seq->alloc * RANGE_SIZE);
}
seq->set[seq->len].low = num;
seq->len++;
Expand All @@ -139,6 +140,44 @@ EXPORTED void seqset_add(seqset_t *seq, unsigned num, int ismember)
seq->prev = num;
}

/*
* Remove a number `num' from the sequence set `seq'.
*/
EXPORTED void seqset_remove(seqset_t *seq, unsigned num)
{
if (!seqset_ismember(seq, num)) return;

struct seq_range *cur = &seq->set[seq->current];

if (cur->low == cur->high) {
/* Single value - remove from the set */
memmove(cur, cur+1, (seq->len - seq->current - 1) * RANGE_SIZE);
seq->len--;
}
else if (num == cur->low) {
/* Increment the low value */
cur->low = num + 1;
}
else if (num == cur->high) {
/* Decrement the high value */
cur->high = num - 1;
}
else {
/* Split the range - insert a new one after current */
if (seq->len == seq->alloc) {
seq->alloc += SETGROWSIZE;
seq->set = xrealloc(seq->set, seq->alloc * RANGE_SIZE);
}

cur = &seq->set[seq->current]; // xrealloc may have changed ptr location
memmove(cur+1, cur, (seq->len - seq->current) + RANGE_SIZE);
seq->len++;

cur->high = num - 1;
(cur+1)->low = num + 1;
}
}


/* read the final number from a sequence string and return it */
EXPORTED unsigned seq_lastnum(const char *list)
Expand Down
1 change: 1 addition & 0 deletions lib/seqset.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ extern unsigned seq_lastnum(const char *list);
/* for writing */
extern seqset_t *seqset_init(unsigned maxval, int flags);
void seqset_add(seqset_t *seq, unsigned num, int ismember);
void seqset_remove(seqset_t *seq, unsigned num);

extern seqset_t *seqset_parse(const char *sequence,
seqset_t *set,
Expand Down

0 comments on commit 53f739e

Please sign in to comment.