Add list_swap() and list_insert() functions (#232)

* Add list_swap() and list_insert() functions

* Update docs for list_swap

* Add test case and fix list insert bug

* Fix silly bug with list length on insertion

* Initial changes for pr

* Add reverse iterator and update test for it

* Cleanup iterator next function

* update tests to cover list_get_at_idx
This commit is contained in:
Rickey
2025-11-18 18:19:00 -08:00
committed by GitHub
parent a4caa44580
commit 47b1bac31f
3 changed files with 563 additions and 17 deletions
+383
View File
@@ -286,6 +286,382 @@ void push_back_three_remove_push_front_three_entries(void)
assert(list_is_empty(&my_cool_list));
}
// Test inserting at head, middle, and tail of list
// - list_create
// - list_push_back
// - list_insert
// - list_is_empty
// - list_get_len
// - list_itr_create
// - rev_list_itr_create
// - list_itr_next
// - list_clear
// - list_get_at_idx
void test_list_insertion(void)
{
List my_cool_list = list_create();
// verify no data
assert(my_cool_list.head == NULL);
assert(my_cool_list.tail == NULL);
assert(list_get_len(&my_cool_list) == 0);
assert(list_is_empty(&my_cool_list));
const int initial_list_size = 5;
int test_data[initial_list_size];
for(int i = 0; i < initial_list_size; i++)
{
test_data[i] = i;
list_push_back(&my_cool_list, &test_data[i]);
}
assert(list_get_len(&my_cool_list) == initial_list_size);
int head_val = 0xDEADBEEF;
int middle_val = 0x1337;
int tail_val = 0x10101010;
int last_tail_val = 0x12345678;
// insert at head of list
list_insert(&my_cool_list, &head_val, 0);
ListItr itr = list_itr_create(&my_cool_list);
void* data;
int test_data_itr = 0;
int index = 0;
while((data = list_itr_next(&itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
if(index == 0)
{
assert(data_itr == head_val);
assert(data_from_get_at_idx == head_val);
}
else
{
assert(data_itr == test_data[test_data_itr]);
assert(data_from_get_at_idx == test_data[test_data_itr]);
test_data_itr++;
}
index++;
}
assert(list_get_len(&my_cool_list) == initial_list_size + 1);
// insert at tail of list, use large value of 100 to force it to append it
// to the end of the list
list_insert(&my_cool_list, &tail_val, 100);
itr = list_itr_create(&my_cool_list);
index = 0;
test_data_itr = 0;
while((data = list_itr_next(&itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
if(index == 0)
{
assert(data_itr == head_val);
assert(data_from_get_at_idx == head_val);
}
else if(index == initial_list_size + 1) // for head and tail insertion
{
assert(data_itr == tail_val);
assert(data_from_get_at_idx == tail_val);
}
else
{
assert(data_itr == test_data[test_data_itr]);
assert(data_from_get_at_idx == test_data[test_data_itr]);
test_data_itr++;
}
index++;
}
assert(list_get_len(&my_cool_list) == initial_list_size + 2);
// insert at "middle" of list
int insert_loc = 2;
test_data_itr = 0;
list_insert(&my_cool_list, &middle_val, insert_loc);
itr = list_itr_create(&my_cool_list);
index = 0;
while((data = list_itr_next(&itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
if(index == 0)
{
assert(data_itr == head_val);
assert(data_from_get_at_idx == head_val);
}
else if(index == insert_loc)
{
assert(data_itr == middle_val);
assert(data_from_get_at_idx == middle_val);
}
else if(index == initial_list_size + 2) // for head+middle+tail
{
assert(data_itr == tail_val);
assert(data_from_get_at_idx == tail_val);
}
else
{
assert(data_itr == test_data[test_data_itr]);
assert(data_from_get_at_idx == test_data[test_data_itr]);
test_data_itr++;
}
index++;
}
printf("\n");
ListItr rev_itr = rev_list_itr_create(&my_cool_list);
index = initial_list_size + 2;
test_data_itr = initial_list_size - 1;
while((data = list_itr_next(&rev_itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
if(index == 0)
{
assert(data_itr == head_val);
assert(data_from_get_at_idx == head_val);
}
else if(index == insert_loc)
{
assert(data_itr == middle_val);
assert(data_from_get_at_idx == middle_val);
}
else if(index == initial_list_size + 2) // for head+middle+tail
{
assert(data_itr == tail_val);
assert(data_from_get_at_idx == tail_val);
}
else
{
assert(data_itr == test_data[test_data_itr]);
assert(data_from_get_at_idx == test_data[test_data_itr]);
test_data_itr--;
}
index--;
}
assert(list_get_len(&my_cool_list) == initial_list_size + 3);
// insert at the real end of the list, to make sure
// it works in conjunction with the previous "out of range" insertion for the tail
int tail_idx = list_get_len(&my_cool_list) - 1;
test_data_itr = 0;
list_insert(&my_cool_list, &last_tail_val, tail_idx);
itr = list_itr_create(&my_cool_list);
index = 0;
while((data = list_itr_next(&itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
if(index == 0)
{
assert(data_itr == head_val);
assert(data_from_get_at_idx == head_val);
}
else if(index == insert_loc)
{
assert(data_itr == middle_val);
assert(data_from_get_at_idx == middle_val);
}
else if(index == initial_list_size + 2) // for head+middle+tail
{
assert(data_itr == last_tail_val);
assert(data_from_get_at_idx == last_tail_val);
}
else if(index == initial_list_size + 3) // for head+middle+tail+last_tail
{
assert(data_itr == tail_val);
assert(data_from_get_at_idx == tail_val);
}
else
{
assert(data_itr == test_data[test_data_itr]);
assert(data_from_get_at_idx == test_data[test_data_itr]);
test_data_itr++;
}
index++;
}
assert(list_get_len(&my_cool_list) == initial_list_size + 4);
// clear the list
list_clear(&my_cool_list);
// verify no data
assert(my_cool_list.head == NULL);
assert(my_cool_list.tail == NULL);
assert(list_is_empty(&my_cool_list));
}
// Test inserting at head, middle, and tail of list
// - list_create
// - list_push_back
// - list_swap
// - list_is_empty
// - list_get_len
// - list_itr_create
// - list_itr_next
// - list_clear
// - list_get_at_idx
void test_list_swap(void)
{
List my_cool_list = list_create();
// verify no data
assert(my_cool_list.head == NULL);
assert(my_cool_list.tail == NULL);
assert(list_get_len(&my_cool_list) == 0);
assert(list_is_empty(&my_cool_list));
const int initial_list_size = 5;
int test_data[initial_list_size];
for(int i = 0; i < initial_list_size; i++)
{
// 0 -> 1 -> 2 -> 3 -> 4
test_data[i] = i;
list_push_back(&my_cool_list, &test_data[i]);
}
assert(list_get_len(&my_cool_list) == initial_list_size);
ListItr itr = list_itr_create(&my_cool_list);
void* data;
int index = 0;
while((data = list_itr_next(&itr)))
{
// 0 -> 1 -> 2 -> 3 -> 4
assert(*(int*)list_get_at_idx(&my_cool_list, index) == test_data[index]);
assert(*(int*)data == test_data[index]);
index++;
}
// swap nothing, out of range
assert(!list_swap(&my_cool_list, 100, 100));
itr = list_itr_create(&my_cool_list);
index = 0;
while((data = list_itr_next(&itr)))
{
// 0 -> 1 -> 2 -> 3 -> 4
assert(*(int*)list_get_at_idx(&my_cool_list, index) == test_data[index]);
assert(*(int*)data == test_data[index]);
index++;
}
// swap nothing, in range
assert(list_swap(&my_cool_list, 0, 0));
itr = list_itr_create(&my_cool_list);
index = 0;
while((data = list_itr_next(&itr)))
{
// 0 -> 1 -> 2 -> 3 -> 4
assert(*(int*)list_get_at_idx(&my_cool_list, index) == test_data[index]);
assert(*(int*)data == test_data[index]);
index++;
}
// swap head and "middle"
int mid_idx = initial_list_size / 2;
assert(list_swap(&my_cool_list, 0, mid_idx));
itr = list_itr_create(&my_cool_list);
index = 0;
while((data = list_itr_next(&itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
// 2 -> 1 -> 0 -> 3 -> 4
if(index == 0)
{
assert(data_itr == test_data[mid_idx]);
assert(data_from_get_at_idx == test_data[mid_idx]);
}
else if(index == mid_idx)
{
assert(data_itr == test_data[0]);
assert(data_from_get_at_idx == test_data[0]);
}
else
{
assert(data_itr == test_data[index]);
assert(data_from_get_at_idx == test_data[index]);
}
index++;
}
// swap tail and "middle"
assert(list_swap(&my_cool_list, initial_list_size - 1, mid_idx));
itr = list_itr_create(&my_cool_list);
index = 0;
while((data = list_itr_next(&itr)))
{
int data_itr = *(int*)data;
int data_from_get_at_idx = *(int*)list_get_at_idx(&my_cool_list, index);
// 2 -> 1 -> 4 -> 3 -> 0
if(index == 0)
{
assert(data_itr == test_data[mid_idx]);
assert(data_from_get_at_idx == test_data[mid_idx]);
}
else if(index == mid_idx)
{
assert(data_itr == test_data[initial_list_size - 1]);
assert(data_from_get_at_idx == test_data[initial_list_size - 1]);
}
else if(index == initial_list_size - 1)
{
assert(data_itr == test_data[0]);
assert(data_from_get_at_idx == test_data[0]);
}
else
{
assert(data_itr == test_data[index]);
assert(data_from_get_at_idx == test_data[index]);
}
index++;
}
// clear the list
list_clear(&my_cool_list);
// verify no data
assert(my_cool_list.head == NULL);
assert(my_cool_list.tail == NULL);
assert(list_is_empty(&my_cool_list));
}
int main(void)
{
printf("Testing List Create and Clear.\n");
@@ -296,9 +672,16 @@ int main(void)
printf("Testing List Push Front.\n");
push_front_one_entry();
printf("Testing List Complete Exercise.\n");
push_back_three_remove_push_front_three_entries();
printf("Testing List Insertion.\n");
test_list_insertion();
printf("Testing List Swap.\n");
test_list_swap();
printf("-------------------------------------------------------------------------------\n");
printf("List Tests Passed :)\n");
printf("-------------------------------------------------------------------------------\n");