aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTucker Evans <tucker@tuckerevans.com>2020-05-27 04:41:40 -0400
committerTucker Evans <tucker@tuckerevans.com>2020-05-27 04:41:40 -0400
commitdbb5ba792719088f99b58a954a53b1cdab213f0c (patch)
tree3e76d6f5b5a0fb1057443927892e47213ec12701
parent735a88c02286a01c2a4edb8f7f6ccf0a93de24b0 (diff)
Fix resize implementation (double ended queue).
Needed to take into account circular buffer i.e. handle a split buffer (base<->end & beg<->limit) along with regular (beg<->end).
-rw-r--r--collections/double_ended_queue.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/collections/double_ended_queue.c b/collections/double_ended_queue.c
index 25f3181..b555e3a 100644
--- a/collections/double_ended_queue.c
+++ b/collections/double_ended_queue.c
@@ -73,25 +73,32 @@ deq *root;
void deq_resize(root)
deq *root;
{
- if (root->beg != root->base) {
- memmove(root->base, root->beg, root->end - root->beg);
- root->end = root->base + deq_size(root);
- root->beg = root->base;
- } else {
- root->base = malloc(root->limit * 2 * sizeof(void*));
- assert(root->base);
+ void **tmp;
+ int size;
+ tmp = malloc(root->limit * 2 * sizeof(void*));
+ assert(root->base);
- root->base = memcpy(root->base, root->beg, root->limit * sizeof(void*));
- assert(root->base);
+ if (root->beg > root->end) {
+ /*copy beg<->limit*/
+ size = (root->base + (root->limit*sizeof(void*)) - root->beg);
+ tmp = memcpy(tmp, root->beg, size * sizeof(void*);
+ assert(tmp);
+ /*copy base<->end*/
+ tmp = memcpy(tmp + size, root->beg,
+ (root->end - root->base)* sizeof(void*));
+ assert(tmp);
+ } else {
+ size = deq_size(root);
+ tmp = memcpy(tmp, root->beg, size*sizeof(void*));
+ }
- root->end = root->base + deq_size(root);
- root->limit = root->limit * 2;
+ root->limit *= 2;
- free(root->beg);
- root->beg = root->base;
- }
+ free(root->base);
+ root->base = root->beg = tmp;
+ root->end = root->base + size;
}
void* deq_index(root, index)