From e834aaee8198c23289697b95e35090d0727910ae Mon Sep 17 00:00:00 2001 From: Leonardo Date: Fri, 13 Sep 2019 18:46:00 -0300 Subject: [PATCH] Added iter_advance, iter_rewind and iter_go_to to all collections Also reworked many iterator functions that could cause strange behavior --- src/cmc/deque.h | 78 ++++++++++++++++------ src/cmc/hashmap.h | 105 +++++++++++++++++++++++------ src/cmc/hashset.h | 105 +++++++++++++++++++++++------ src/cmc/heap.h | 104 +++++++++++++++++++++++++---- src/cmc/linkedlist.h | 116 ++++++++++++++++++++++++++------ src/cmc/list.h | 97 +++++++++++++++++++++++---- src/cmc/queue.h | 94 ++++++++++++++++++++++---- src/cmc/stack.h | 107 +++++++++++++++++++++++------- src/cmc/treemap.h | 135 ++++++++++++++++++++++++++++--------- src/cmc/treeset.h | 133 +++++++++++++++++++++++++++++-------- src/ext/intervalheap.h | 101 ++++++++++++++++++++++++---- src/ext/multimap.h | 117 ++++++++++++++++++++++++-------- src/ext/multiset.h | 147 ++++++++++++++++++++++++++++++----------- 13 files changed, 1154 insertions(+), 285 deletions(-) diff --git a/src/cmc/deque.h b/src/cmc/deque.h index 25a0005..0e23aeb 100644 --- a/src/cmc/deque.h +++ b/src/cmc/deque.h @@ -472,11 +472,16 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ + { \ iter->cursor = 0; \ + iter->index = 0; \ + } \ else \ + { \ iter->cursor = (iter->target->back == 0) ? iter->target->capacity - 1 : iter->target->back - 1; \ + iter->index = PFX##_count(iter->target) - 1; \ + } \ \ - iter->index = iter->target->count - 1; \ iter->start = PFX##_empty(iter->target); \ iter->end = true; \ } \ @@ -486,15 +491,16 @@ if (iter->end) \ return false; \ \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ iter->start = PFX##_empty(iter->target); \ \ - if (iter->index == iter->target->count - 1) \ - iter->end = true; \ - else \ - { \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - iter->index++; \ - } \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->index++; \ \ return true; \ } \ @@ -504,49 +510,81 @@ if (iter->start) \ return false; \ \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ iter->end = PFX##_empty(iter->target); \ \ - if (iter->index == 0) \ - iter->start = true; \ - else \ - { \ - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ - iter->index--; \ - } \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ + iter->index--; \ \ return true; \ } \ \ + /* Returns true only if the iterator moved */ \ FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ { \ if (iter->end) \ return false; \ \ - if (iter->index + steps > PFX##_count(iter->target)) \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ return false; \ \ - /* TODO */ \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->index += steps; \ + iter->cursor = (iter->cursor + steps) % iter->target->capacity; \ \ return true; \ } \ \ + /* Returns true only if the iterator moved */ \ FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ { \ if (iter->start) \ return false; \ \ - if (iter->index < steps) \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ return false; \ \ - /* TODO */ \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->index -= steps; \ + \ + /* Prevent underflow */ \ + if (iter->cursor < steps) \ + iter->cursor += PFX##_capacity(iter->target); \ + \ + iter->cursor -= steps; \ \ return true; \ } \ \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ \ - /* TODO */ \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ \ return true; \ } \ diff --git a/src/cmc/hashmap.h b/src/cmc/hashmap.h index 4f50962..938f4ea 100644 --- a/src/cmc/hashmap.h +++ b/src/cmc/hashmap.h @@ -195,6 +195,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD K PFX##_iter_key(SNAME##_iter *iter); \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ @@ -618,9 +621,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ iter->target = target; \ - iter->cursor = 0; \ - iter->index = 0; \ iter->start = true; \ iter->end = PFX##_empty(target); \ \ @@ -660,18 +663,24 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = PFX##_count(iter->target) - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -679,15 +688,16 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (iter->end) \ return false; \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->last) \ + if (iter->index + 1 == PFX##_count(iter->target)) \ { \ iter->end = true; \ - \ return false; \ } \ \ + iter->start = PFX##_empty(iter->target); \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ iter->index++; \ \ while (1) \ @@ -699,8 +709,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, break; \ } \ \ - iter->start = PFX##_empty(iter->target); \ - \ return true; \ } \ \ @@ -709,15 +717,16 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (iter->start) \ return false; \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->first) \ + if (iter->index == 0) \ { \ iter->start = true; \ - \ return false; \ } \ \ + iter->end = PFX##_empty(iter->target); \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ iter->index--; \ \ while (1) \ @@ -729,7 +738,61 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, break; \ } \ \ - iter->end = PFX##_empty(iter->target); \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ \ return true; \ } \ diff --git a/src/cmc/hashset.h b/src/cmc/hashset.h index 75a990c..d36f6e2 100644 --- a/src/cmc/hashset.h +++ b/src/cmc/hashset.h @@ -198,6 +198,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ @@ -742,9 +745,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ iter->target = target; \ - iter->cursor = 0; \ - iter->index = 0; \ iter->start = true; \ iter->end = PFX##_empty(target); \ \ @@ -784,18 +787,24 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = PFX##_count(iter->target) - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -803,15 +812,16 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (iter->end) \ return false; \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->last) \ + if (iter->index + 1 == PFX##_count(iter->target)) \ { \ iter->end = true; \ - \ return false; \ } \ \ + iter->start = PFX##_empty(iter->target); \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ iter->index++; \ \ while (1) \ @@ -823,8 +833,6 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, break; \ } \ \ - iter->start = PFX##_empty(iter->target); \ - \ return true; \ } \ \ @@ -833,15 +841,16 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (iter->start) \ return false; \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->first) \ + if (iter->index == 0) \ { \ iter->start = true; \ - \ return false; \ } \ \ + iter->end = PFX##_empty(iter->target); \ + \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ iter->index--; \ \ while (1) \ @@ -853,7 +862,61 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, break; \ } \ \ - iter->end = PFX##_empty(iter->target); \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ \ return true; \ } \ diff --git a/src/cmc/heap.h b/src/cmc/heap.h index 6d99d84..5859929 100644 --- a/src/cmc/heap.h +++ b/src/cmc/heap.h @@ -137,6 +137,9 @@ typedef enum cmc_heap_order_e FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ @@ -410,16 +413,22 @@ typedef enum cmc_heap_order_e \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = PFX##_count(iter->target) - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -427,12 +436,15 @@ typedef enum cmc_heap_order_e if (iter->end) \ return false; \ \ - iter->start = false; \ - \ - if (iter->cursor == iter->target->count - 1) \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ iter->end = true; \ - else \ - iter->cursor++; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ \ return true; \ } \ @@ -442,12 +454,76 @@ typedef enum cmc_heap_order_e if (iter->start) \ return false; \ \ - iter->end = false; \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + if (iter->end) \ + return false; \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ \ if (iter->cursor == 0) \ + { \ iter->start = true; \ - else \ - iter->cursor--; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor -= steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->cursor > index) \ + return PFX##_iter_rewind(iter, iter->cursor - index); \ + else if (iter->cursor < index) \ + return PFX##_iter_advance(iter, index - iter->cursor); \ \ return true; \ } \ diff --git a/src/cmc/linkedlist.h b/src/cmc/linkedlist.h index 71aedce..b671f61 100644 --- a/src/cmc/linkedlist.h +++ b/src/cmc/linkedlist.h @@ -162,6 +162,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ @@ -755,18 +758,24 @@ \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = iter->target->head; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->head; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->target->tail; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->tail; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -774,15 +783,16 @@ if (iter->end) \ return false; \ \ + if (iter->cursor->next == NULL) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ iter->start = PFX##_empty(iter->target); \ \ - if (iter->cursor->next == NULL) \ - iter->end = true; \ - else \ - { \ - iter->cursor = iter->cursor->next; \ - iter->index++; \ - } \ + iter->cursor = iter->cursor->next; \ + iter->index++; \ \ return true; \ } \ @@ -792,16 +802,82 @@ if (iter->start) \ return false; \ \ + if (iter->cursor->prev == NULL) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ iter->end = PFX##_empty(iter->target); \ \ - if (iter->cursor->prev == NULL) \ - iter->start = true; \ - else \ + iter->cursor = iter->cursor->prev; \ + iter->index--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor->next == NULL) \ { \ - iter->cursor = iter->cursor->prev; \ - iter->index--; \ + iter->end = true; \ + return false; \ } \ \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->index += steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + iter->cursor = iter->cursor->next; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor->prev == NULL) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->index -= steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + iter->cursor = iter->cursor->prev; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given */ \ + /* index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ return true; \ } \ \ diff --git a/src/cmc/list.h b/src/cmc/list.h index f1a84d3..2d5ba5b 100644 --- a/src/cmc/list.h +++ b/src/cmc/list.h @@ -153,6 +153,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ @@ -649,16 +652,22 @@ \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->start = PFX##_empty(iter->target); \ - iter->cursor = PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->start = PFX##_empty(iter->target); \ + iter->cursor = PFX##_empty(iter->target) ? 0 : iter->target->count - 1; \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -666,12 +675,15 @@ if (iter->end) \ return false; \ \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ iter->start = PFX##_empty(iter->target); \ \ - if (iter->cursor == iter->target->count - 1) \ - iter->end = true; \ - else \ - iter->cursor++; \ + iter->cursor++; \ \ return true; \ } \ @@ -681,12 +693,73 @@ if (iter->start) \ return false; \ \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ iter->end = PFX##_empty(iter->target); \ \ + iter->cursor--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor + 1 == iter->target->count) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ if (iter->cursor == 0) \ + { \ iter->start = true; \ - else \ - iter->cursor--; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor -= steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->cursor > index) \ + return PFX##_iter_rewind(iter, iter->cursor - index); \ + else if (iter->cursor < index) \ + return PFX##_iter_advance(iter, index - iter->cursor); \ \ return true; \ } \ diff --git a/src/cmc/queue.h b/src/cmc/queue.h index e1c1996..079eb85 100644 --- a/src/cmc/queue.h +++ b/src/cmc/queue.h @@ -146,6 +146,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ @@ -433,15 +436,16 @@ if (iter->end) \ return false; \ \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ iter->start = PFX##_empty(iter->target); \ \ - if (iter->index == iter->target->count - 1) \ - iter->end = true; \ - else \ - { \ - iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ - iter->index++; \ - } \ + iter->cursor = (iter->cursor + 1) % (iter->target->capacity); \ + iter->index++; \ \ return true; \ } \ @@ -451,16 +455,82 @@ if (iter->start) \ return false; \ \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ iter->end = PFX##_empty(iter->target); \ \ - if (iter->index == 0) \ - iter->start = true; \ - else \ + iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ + iter->index--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ { \ - iter->cursor = (iter->cursor == 0) ? iter->target->capacity - 1 : iter->cursor - 1; \ - iter->index--; \ + iter->end = true; \ + return false; \ } \ \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->index += steps; \ + iter->cursor = (iter->cursor + steps) % iter->target->capacity; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->index -= steps; \ + \ + /* Prevent underflow */ \ + if (iter->cursor < steps) \ + iter->cursor += PFX##_capacity(iter->target); \ + \ + iter->cursor -= steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ return true; \ } \ \ diff --git a/src/cmc/stack.h b/src/cmc/stack.h index 7a2ea22..4b3290a 100644 --- a/src/cmc/stack.h +++ b/src/cmc/stack.h @@ -122,6 +122,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD V *PFX##_iter_rvalue(SNAME##_iter *iter); \ @@ -343,12 +346,7 @@ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ iter->target = target; \ - \ - if (PFX##_empty(target)) \ - iter->cursor = 0; \ - else \ - iter->cursor = iter->target->count - 1; \ - \ + iter->cursor = PFX##_empty(target) ? 0 : iter->target->count - 1; \ iter->start = true; \ iter->end = PFX##_empty(target); \ } \ @@ -365,16 +363,22 @@ \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = iter->target->count - 1; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->count - 1; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = 0; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -382,16 +386,15 @@ if (iter->end) \ return false; \ \ - iter->start = PFX##_empty(iter->target); \ - \ if (iter->cursor == 0) \ { \ iter->end = true; \ - \ return false; \ } \ - else \ - iter->cursor--; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor--; \ \ return true; \ } \ @@ -401,16 +404,74 @@ if (iter->start) \ return false; \ \ - iter->end = PFX##_empty(iter->target); \ - \ - if (iter->cursor == iter->target->count - 1) \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ { \ iter->start = true; \ - \ return false; \ } \ - else \ - iter->cursor++; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor -= steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given */ \ + /* index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->cursor > index) \ + return PFX##_iter_rewind(iter, iter->cursor - index); \ + else if (iter->cursor < index) \ + return PFX##_iter_advance(iter, index - iter->cursor); \ \ return true; \ } \ diff --git a/src/cmc/treemap.h b/src/cmc/treemap.h index b2b6c1a..b1f063e 100644 --- a/src/cmc/treemap.h +++ b/src/cmc/treemap.h @@ -147,6 +147,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD K PFX##_iter_key(SNAME##_iter *iter); \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ @@ -650,20 +653,25 @@ \ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ iter->target = target; \ - iter->index = 0; \ iter->start = true; \ iter->end = PFX##_empty(target); \ \ iter->cursor = target->root; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ \ - iter->first = iter->cursor; \ + if (!PFX##_empty(target)) \ + { \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ } \ \ FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ @@ -678,20 +686,24 @@ \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->cursor = iter->first; \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->cursor = iter->last; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -699,11 +711,18 @@ if (iter->end) \ return false; \ \ - iter->start = false; \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ \ if (iter->cursor->right != NULL) \ { \ iter->cursor = iter->cursor->right; \ + \ while (iter->cursor->left != NULL) \ iter->cursor = iter->cursor->left; \ \ @@ -714,12 +733,6 @@ \ while (true) \ { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - \ - return true; \ - } \ if (iter->cursor->parent->left == iter->cursor) \ { \ iter->cursor = iter->cursor->parent; \ @@ -738,7 +751,13 @@ if (iter->start) \ return false; \ \ - iter->end = false; \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ \ if (iter->cursor->left != NULL) \ { \ @@ -754,12 +773,6 @@ \ while (true) \ { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ if (iter->cursor->parent->right == iter->cursor) \ { \ iter->cursor = iter->cursor->parent; \ @@ -773,6 +786,66 @@ } \ } \ \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->index += steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->index -= steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ FMOD K PFX##_iter_key(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ diff --git a/src/cmc/treeset.h b/src/cmc/treeset.h index d6ede3a..7cb5f95 100644 --- a/src/cmc/treeset.h +++ b/src/cmc/treeset.h @@ -152,6 +152,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ @@ -792,20 +795,25 @@ \ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ iter->target = target; \ - iter->index = 0; \ iter->start = true; \ iter->end = PFX##_empty(target); \ \ iter->cursor = target->root; \ - while (iter->cursor->left != NULL) \ - iter->cursor = iter->cursor->left; \ \ - iter->first = iter->cursor; \ + if (!PFX##_empty(target)) \ + { \ + while (iter->cursor->left != NULL) \ + iter->cursor = iter->cursor->left; \ \ - iter->last = target->root; \ - while (iter->last->right != NULL) \ - iter->last = iter->last->right; \ + iter->first = iter->cursor; \ + \ + iter->last = target->root; \ + while (iter->last->right != NULL) \ + iter->last = iter->last->right; \ + } \ } \ \ FMOD bool PFX##_iter_start(SNAME##_iter *iter) \ @@ -820,20 +828,24 @@ \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - \ - iter->cursor = iter->first; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->cursor = iter->first; \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - \ - iter->cursor = iter->last; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->cursor = iter->last; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -841,11 +853,18 @@ if (iter->end) \ return false; \ \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return true; \ + } \ + \ iter->start = PFX##_empty(iter->target); \ \ if (iter->cursor->right != NULL) \ { \ iter->cursor = iter->cursor->right; \ + \ while (iter->cursor->left != NULL) \ iter->cursor = iter->cursor->left; \ \ @@ -856,12 +875,6 @@ \ while (true) \ { \ - if (iter->cursor == iter->last) \ - { \ - iter->end = true; \ - \ - return true; \ - } \ if (iter->cursor->parent->left == iter->cursor) \ { \ iter->cursor = iter->cursor->parent; \ @@ -880,11 +893,19 @@ if (iter->start) \ return false; \ \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + \ + return true; \ + } \ + \ iter->end = PFX##_empty(iter->target); \ \ if (iter->cursor->left != NULL) \ { \ iter->cursor = iter->cursor->left; \ + \ while (iter->cursor->right != NULL) \ iter->cursor = iter->cursor->right; \ \ @@ -895,12 +916,6 @@ \ while (true) \ { \ - if (iter->cursor == iter->first) \ - { \ - iter->start = true; \ - \ - return true; \ - } \ if (iter->cursor->parent->right == iter->cursor) \ { \ iter->cursor = iter->cursor->parent; \ @@ -914,6 +929,66 @@ } \ } \ \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->cursor == iter->last) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->index += steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == iter->first) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + iter->index -= steps; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ FMOD V PFX##_iter_value(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ diff --git a/src/ext/intervalheap.h b/src/ext/intervalheap.h index ce5f43d..1d3f678 100644 --- a/src/ext/intervalheap.h +++ b/src/ext/intervalheap.h @@ -136,6 +136,9 @@ FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD size_t PFX##_iter_index(SNAME##_iter *iter); \ @@ -597,16 +600,22 @@ \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -614,12 +623,15 @@ if (iter->end) \ return false; \ \ - iter->start = false; \ - \ - if (iter->cursor == iter->target->count - 1) \ + if (iter->cursor + 1 == PFX##_count(iter->target)) \ + { \ iter->end = true; \ - else \ - iter->cursor++; \ + return false; \ + } \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor++; \ \ return true; \ } \ @@ -629,12 +641,73 @@ if (iter->start) \ return false; \ \ - iter->end = false; \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor--; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ \ if (iter->cursor == 0) \ + { \ iter->start = true; \ - else \ - iter->cursor--; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + iter->start = PFX##_empty(iter->target); \ + \ + iter->cursor += steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->cursor == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->cursor < steps) \ + return false; \ + \ + iter->end = PFX##_empty(iter->target); \ + \ + iter->cursor -= steps; \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->cursor > index) \ + return PFX##_iter_rewind(iter, iter->cursor - index); \ + else if (iter->cursor < index) \ + return PFX##_iter_advance(iter, index - iter->cursor); \ \ return true; \ } \ diff --git a/src/ext/multimap.h b/src/ext/multimap.h index ec5c580..a57114a 100644 --- a/src/ext/multimap.h +++ b/src/ext/multimap.h @@ -217,6 +217,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD K PFX##_iter_key(SNAME##_iter *iter); \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ @@ -808,9 +811,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ iter->target = target; \ - iter->cursor = 0; \ - iter->index = 0; \ iter->start = true; \ iter->end = PFX##_empty(target); \ \ @@ -851,20 +854,26 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ - iter->curr_entry = iter->target->buffer[iter->first][0]; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + iter->curr_entry = iter->target->buffer[iter->first][0]; \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ - iter->curr_entry = iter->target->buffer[iter->last][1]; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + iter->curr_entry = iter->target->buffer[iter->last][1]; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -884,17 +893,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, iter->end = true; \ return false; \ } \ - else \ - { \ + \ + iter->cursor++; \ + \ + while (iter->target->buffer[iter->cursor][0] == NULL) \ iter->cursor++; \ \ - while (iter->target->buffer[iter->cursor][0] == NULL) \ - iter->cursor++; \ + iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ \ - iter->curr_entry = iter->target->buffer[iter->cursor][0]; \ - \ - iter->index++; \ - } \ + iter->index++; \ } \ \ iter->start = PFX##_empty(iter->target); \ @@ -919,17 +926,15 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, iter->start = true; \ return false; \ } \ - else \ - { \ + \ + iter->cursor--; \ + \ + while (iter->target->buffer[iter->cursor][1] == NULL) \ iter->cursor--; \ \ - while (iter->target->buffer[iter->cursor][1] == NULL) \ - iter->cursor--; \ + iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ \ - iter->curr_entry = iter->target->buffer[iter->cursor][1]; \ - \ - iter->index--; \ - } \ + iter->index--; \ } \ \ iter->end = PFX##_empty(iter->target); \ @@ -937,6 +942,62 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, return true; \ } \ \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ + return true; \ + } \ + \ FMOD K PFX##_iter_key(SNAME##_iter *iter) \ { \ if (PFX##_empty(iter->target)) \ diff --git a/src/ext/multiset.h b/src/ext/multiset.h index 3603385..e15cfdf 100644 --- a/src/ext/multiset.h +++ b/src/ext/multiset.h @@ -213,6 +213,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, FMOD void PFX##_iter_to_end(SNAME##_iter *iter); \ FMOD bool PFX##_iter_next(SNAME##_iter *iter); \ FMOD bool PFX##_iter_prev(SNAME##_iter *iter); \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps); \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index); \ /* Iterator Access */ \ FMOD V PFX##_iter_value(SNAME##_iter *iter); \ FMOD size_t PFX##_iter_multiplicity(SNAME##_iter *iter); \ @@ -858,9 +861,9 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_init(SNAME##_iter *iter, SNAME *target) \ { \ + memset(iter, 0, sizeof(SNAME##_iter)); \ + \ iter->target = target; \ - iter->cursor = 0; \ - iter->index = 0; \ iter->start = true; \ iter->end = PFX##_empty(target); \ \ @@ -900,18 +903,24 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, \ FMOD void PFX##_iter_to_start(SNAME##_iter *iter) \ { \ - iter->cursor = iter->first; \ - iter->index = 0; \ - iter->start = true; \ - iter->end = PFX##_empty(iter->target); \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->first; \ + iter->index = 0; \ + iter->start = true; \ + iter->end = PFX##_empty(iter->target); \ + } \ } \ \ FMOD void PFX##_iter_to_end(SNAME##_iter *iter) \ { \ - iter->cursor = iter->last; \ - iter->index = iter->target->count - 1; \ - iter->start = PFX##_empty(iter->target); \ - iter->end = true; \ + if (!PFX##_empty(iter->target)) \ + { \ + iter->cursor = iter->last; \ + iter->index = iter->target->count - 1; \ + iter->start = PFX##_empty(iter->target); \ + iter->end = true; \ + } \ } \ \ FMOD bool PFX##_iter_next(SNAME##_iter *iter) \ @@ -919,26 +928,27 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (iter->end) \ return false; \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->last) \ - iter->end = true; \ - else \ + if (iter->index + 1 == PFX##_count(iter->target)) \ { \ - iter->index++; \ - \ - while (1) \ - { \ - iter->cursor++; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ + iter->end = true; \ + return false; \ } \ \ iter->start = PFX##_empty(iter->target); \ \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + iter->index++; \ + \ + while (1) \ + { \ + iter->cursor++; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == CMC_ES_FILLED) \ + break; \ + } \ + \ return true; \ } \ \ @@ -947,26 +957,83 @@ static const size_t cmc_hashtable_primes[] = {53, 97, 191, 383, 769, 1531, if (iter->start) \ return false; \ \ - SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (iter->cursor == iter->first) \ - iter->start = true; \ - else \ + if (iter->index == 0) \ { \ - iter->index--; \ - \ - while (1) \ - { \ - iter->cursor--; \ - scan = &(iter->target->buffer[iter->cursor]); \ - \ - if (scan->state == CMC_ES_FILLED) \ - break; \ - } \ + iter->start = true; \ + return false; \ } \ \ iter->end = PFX##_empty(iter->target); \ \ + SNAME##_entry *scan = &(iter->target->buffer[iter->cursor]); \ + \ + iter->index--; \ + \ + while (1) \ + { \ + iter->cursor--; \ + scan = &(iter->target->buffer[iter->cursor]); \ + \ + if (scan->state == CMC_ES_FILLED) \ + break; \ + } \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_advance(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->end) \ + return false; \ + \ + if (iter->index + 1 == PFX##_count(iter->target)) \ + { \ + iter->end = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index + steps >= PFX##_count(iter->target)) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_next(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator moved */ \ + FMOD bool PFX##_iter_rewind(SNAME##_iter *iter, size_t steps) \ + { \ + if (iter->start) \ + return false; \ + \ + if (iter->index == 0) \ + { \ + iter->start = true; \ + return false; \ + } \ + \ + if (steps == 0 || iter->index < steps) \ + return false; \ + \ + for (size_t i = 0; i < steps; i++) \ + PFX##_iter_prev(iter); \ + \ + return true; \ + } \ + \ + /* Returns true only if the iterator was able to be positioned at the given index */ \ + FMOD bool PFX##_iter_go_to(SNAME##_iter *iter, size_t index) \ + { \ + if (index >= PFX##_count(iter->target)) \ + return false; \ + \ + if (iter->index > index) \ + return PFX##_iter_rewind(iter, iter->index - index); \ + else if (iter->index < index) \ + return PFX##_iter_advance(iter, index - iter->index); \ + \ return true; \ } \ \