diff --git a/src/UDPC_Deque.c b/src/UDPC_Deque.c index 6dff813..7675b87 100644 --- a/src/UDPC_Deque.c +++ b/src/UDPC_Deque.c @@ -328,6 +328,61 @@ int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, v return 1; } +int UDPC_Deque_remove(UDPC_Deque *deque, uint32_t unitSize, uint32_t index) +{ + uint32_t pos = unitSize * index; + uint32_t abspos; + uint32_t lastpos; + if(deque->size == 0 || pos >= deque->size) + { + return 0; + } + else if(deque->size <= unitSize) + { + UDPC_Deque_clear(deque); + return 1; + } + + if(pos + deque->head >= deque->alloc_size) + { + abspos = pos + deque->head - deque->alloc_size; + } + else + { + abspos = pos + deque->head; + } + + if(deque->tail == 0) + { + lastpos = deque->alloc_size - unitSize; + } + else + { + lastpos = deque->tail - unitSize; + } + + if(abspos != lastpos) + { + if(deque->tail == 0) + { + memcpy(&deque->buf[abspos], &deque->buf[deque->alloc_size - unitSize], unitSize); + deque->tail = deque->alloc_size - unitSize; + } + else + { + memcpy(&deque->buf[abspos], &deque->buf[deque->tail - unitSize], unitSize); + deque->tail -= unitSize; + } + deque->size -= unitSize; + } + else + { + UDPC_Deque_pop_back(deque, unitSize); + } + + return 1; +} + void UDPC_Deque_clear(UDPC_Deque *deque) { deque->head = 0; diff --git a/src/UDPC_Deque.h b/src/UDPC_Deque.h index 14929f1..54590a1 100644 --- a/src/UDPC_Deque.h +++ b/src/UDPC_Deque.h @@ -109,6 +109,13 @@ int UDPC_Deque_index(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void */ int UDPC_Deque_index_rev(UDPC_Deque *deque, uint32_t unitSize, uint32_t index, void **out); +/*! + * \brief Replaces the data at index with data at the end (if exists) + * Note this will reduce the size of the Deque by unitSize amount. + * \return non-zero if data was removed + */ +int UDPC_Deque_remove(UDPC_Deque *deque, uint32_t unitSize, uint32_t index); + void UDPC_Deque_clear(UDPC_Deque *deque); #endif diff --git a/src/test/UDPC_UnitTest.c b/src/test/UDPC_UnitTest.c index 1e0d173..01d5f89 100644 --- a/src/test/UDPC_UnitTest.c +++ b/src/test/UDPC_UnitTest.c @@ -166,7 +166,35 @@ int main() ASSERT_FALSE(UDPC_Deque_index_rev(deque, sizeof(int), 8, (void**)&temp)); ASSERT_FALSE(temp); + // remove success front + ASSERT_TRUE(UDPC_Deque_remove(deque, sizeof(int), 0)); + ASSERT_EQ(sizeof(int) * 7, deque->size); + ASSERT_EQ_MEM(deque->buf, &arr[7], sizeof(int)); + + // remove success end + ASSERT_TRUE(UDPC_Deque_remove(deque, sizeof(int), 6)); + ASSERT_EQ(sizeof(int) * 6, deque->size); + ASSERT_EQ_MEM(&deque->buf[deque->tail - sizeof(int)], &arr[5], sizeof(int)); + + // remove success middle + ASSERT_TRUE(UDPC_Deque_remove(deque, sizeof(int), 2)); + ASSERT_EQ(sizeof(int) * 5, deque->size); + ASSERT_EQ_MEM(&deque->buf[deque->head + sizeof(int) * 2], &arr[5], sizeof(int)); + + // remove success until empty + while(deque->size > 0) + { + ASSERT_TRUE(UDPC_Deque_remove(deque, sizeof(int), 0)); + } + ASSERT_EQ(deque->size, 0); + /* + for(int x = 0; x < deque->tail / sizeof(int); ++x) + { + temp = &deque->buf[x * sizeof(int)]; + printf("%d: %d ", x, *((int*)temp)); + } + printf("\n"); printf("asize %d, size %d, head %d, tail %d\n", deque->alloc_size, deque->size, deque->head, deque->tail); */