1
0
Fork 0

Started fixing bugs in vector, still not done (check TODO in vector.c).

This commit is contained in:
wael 2021-12-31 18:49:02 +02:00
parent 599b92d77d
commit 913fa38663
No known key found for this signature in database
GPG Key ID: C0A5FBF4558963D4
3 changed files with 54 additions and 23 deletions

View File

@ -8,11 +8,11 @@
#define PRINT_INFO_TESTING_END "Done testing.\n"
#define SOME_TEST_FAILED "Recheck the tests, one of them failed!\n"
#define TEST_CODE_FAILURE "Error in test code, rerun!\n"
#define INITIAL_VECTOR_SIZE 0
#define INITIAL_VECTOR_SIZE 8
#define VECTOR_SIZE_ONE 1
#define VECTOR_SIZE_TWO 2
#define VECTOR_SIZE_LONG_TEST 4096
#define VECTOR_LAST_ELEMENT_EMPTY_INDEX -1
#define VECTOR_LAST_ELEMENT_EMPTY_INDEX 0
/* Define functions. */
@ -40,6 +40,7 @@ int test_vector() {
assert(vector->length == INITIAL_VECTOR_SIZE);
assert(vector->array != NULL);
assert(vector->last_element == VECTOR_LAST_ELEMENT_EMPTY_INDEX);
assert(vector->empty);
/* Allocate and insert a value. */
value = (int*) malloc(sizeof(int));
@ -55,6 +56,7 @@ int test_vector() {
assert(vector->length == INITIAL_VECTOR_SIZE);
assert(vector->array != NULL);
assert(vector->last_element != VECTOR_LAST_ELEMENT_EMPTY_INDEX);
assert(!vector->empty);
/* Attempt to free. */
free_vector(vector, NULL);

View File

@ -21,8 +21,6 @@
#include "vector.h"
#endif /* VECTOR_C */
/* TODO: fix all the use of void* and change it to use void_ptr for better legibility and (hopefully) less mistakes. */
/* Function implementations. */
/* This function initializes a new empty vector, returns NULL on failure. */
@ -41,6 +39,7 @@ static inline vector_t* initialize_vector() {
vector->length = powl(GROWTH_CONSTANT_VECTOR_C, INITIAL_POWER_VECTOR_C);
vector->element_size = sizeof(void*); /* For better portability. */
vector->last_element = (size_t) LAST_ELEMENT_EMPTY_INDEX_VECTOR_C;
vector->empty = (char) TRUE;
/* Attempt to allocate the array. */
vector->array = (void_ptr*) malloc(vector->length * sizeof(void*));
@ -60,16 +59,22 @@ static inline vector_t* initialize_vector() {
/* Undefined behavior for NULL vectors. */
static inline int append_to_vector(vector_t* vector, void* const data) {
/* Check if the vector has enough space. */
if (check_size_change_vector(vector, THRESHOLD_GROW_VECTOR_C)) {
if (check_vector_grow(vector, THRESHOLD_GROW_VECTOR_C)) {
/* Grow the vector. */
if (!grow_vector(vector))
return FAILURE_CODE_VECTOR_C;
}
/* Add the value to the end. */ /* TODO: check!! */
*(vector->array + (((vector->last_element == (size_t) LAST_ELEMENT_EMPTY_INDEX_VECTOR_C) ? 0 : vector->last_element) * vector->element_size)) = data;
/* Increment the internal index. */
vector->last_element = vector->last_element + 1L;
/* Add the value to the end. */
*(vector->array + (((vector->empty) ? 0 : vector->last_element) * vector->element_size)) = data;
/* Set the vector to be non-empty and set the index correctly if needed. */
if (vector->empty) {
vector->empty = (char) FALSE;
vector->last_element = 0L;
} else {
/* Increment the internal index. */
vector->last_element = vector->last_element + 1L;
}
/* Return success. */
return SUCCESS_CODE_VECTOR_C;
@ -81,12 +86,16 @@ static inline int append_to_vector(vector_t* vector, void* const data) {
/* Undefined behavior for NULL vectors. */
static inline int prepend_to_vector(vector_t* const vector, void* const data) {
/* Check if the vector has enough space. */
if (check_size_change_vector(vector, THRESHOLD_GROW_VECTOR_C)) {
if (check_vector_grow(vector, THRESHOLD_GROW_VECTOR_C)) {
/* Grow the vector. */
if (!grow_vector(vector))
return FAILURE_CODE_VECTOR_C;
}
/* Check if the vector is empty. */
if (vector->empty)
return append_to_vector(vector, data);
/* Push the vector by 1. */
push_vector(vector, 1L);
@ -105,7 +114,7 @@ static inline int prepend_to_vector(vector_t* const vector, void* const data) {
/* Undefined behavior for NULL vectors. */
static inline void* read_from_vector(const vector_t* const vector, const size_t index, int* const error) {
/* Check if read index is within bounds. */
if (vector->last_element < index) {
if (vector->last_element < index || vector->empty) {
/* Index out of bounds. */
*error = INDEX_NOT_FOUND_CODE_VECTOR_C;
return NULL;
@ -125,6 +134,10 @@ static inline int write_to_vector(vector_t* const vector, const size_t index, vo
if ((vector->length <= index) || ((vector->last_element + 1L) < index))
return INDEX_NOT_FOUND_CODE_VECTOR_C;
/* Check if the vector is empty. */
if (vector->empty)
return append_to_vector(vector, data);
/* Check if the write is over-writing or not. */
/* Check for an append call. */
if (index == (vector->last_element + 1L))
@ -134,7 +147,7 @@ static inline int write_to_vector(vector_t* const vector, const size_t index, vo
vector->last_element = vector->last_element + 1L;
/* Check if the vector needs to be grown. */
if (check_size_change_vector(vector, THRESHOLD_GROW_VECTOR_C))
if (check_vector_grow(vector, THRESHOLD_GROW_VECTOR_C))
return (grow_vector(vector)) ? SUCCESS_CODE_VECTOR_C : WRITE_SUCCESS_VECTOR_GROW_FAIL_VECTOR_C;
/* Done. */
@ -155,7 +168,7 @@ static inline int delete_from_vector(vector_t* const vector, const size_t index,
if (free_function == NULL)
return INVALID_FREE_FUNCTION_POINTER;
/* Check if delete index is within bounds. */
if ((vector->length <= index) || ((vector->last_element + 1L) < index))
if (vector->empty || (vector->length <= index) || ((vector->last_element + 1L) < index))
return INDEX_NOT_FOUND_CODE_VECTOR_C;
/* Free the internal data. */
@ -172,6 +185,10 @@ static inline int delete_from_vector(vector_t* const vector, const size_t index,
/* Move back the last element by 1. */
vector->last_element -= 1L;
/* Check if the vector should be shrunk. */
if (check_vector_shrink(vector, THRESHOLD_SHRINK_VECTOR_C))
/* TODO: implement. */
/* Done. */
return SUCCESS_CODE_VECTOR_C;
}
@ -180,6 +197,7 @@ static inline int delete_from_vector(vector_t* const vector, const size_t index,
/* Returns NULL on allocation failure. */
/* Will exhibit undefined behavior if the vector is NULL or is internally undefined. */
/* Caller should free the allocated buffer! */
/* Note that calling this function on an empty vector might result in Undefined Behavior. */
static inline void_ptr* serialize_vector(const vector_t* const vector) {
/* Attempt to allocate the new buffer. */
void_ptr *buffer = (void_ptr*) malloc(vector->length * vector->element_size);
@ -207,6 +225,7 @@ static inline int copy_vector(vector_t *restrict source, vector_t **restrict des
(*destination)->length = source->length;
(*destination)->element_size = source->element_size;
(*destination)->last_element = source->last_element;
(*destination)->empty = source->empty;
(*destination)->array = serialize_vector(source);
/* Check if the copy failed. */
@ -240,18 +259,21 @@ static inline void free_vector(vector_t *vector, void (*free_function)(const voi
}
/* Internal functions. */
/* This function checks if the vector needs to be grown, shrunk or kept as is. */
static inline int check_size_change_vector(const vector_t* const vector, const double threshold) {
/* This function checks if the vector needs to be grown or kept as is. */
static inline int check_vector_grow(const vector_t* const vector, const double threshold) {
/* Calculate the threshold and length. */
size_t current_size = vector->last_element;
size_t current_threshold = (size_t)((vector->length) * threshold);
/* Check if it needs to be grown. */
if (current_size >= current_threshold)
return CODE_GROW_VECTOR_C;
return (current_size >= current_threshold) ? CODE_GROW_VECTOR_C : CODE_KEEP_VECTOR_C;
}
/* Calculate the new threshold for shrinking the vector. */
current_threshold = (size_t)((vector->length) * (THRESHOLD_WHOLE_VECTOR_C - threshold));
/* Return according to if it needs to be shrunk or kept at the same size. */
/* This function checks if the vector needs to be shrunk or kept as is. */
static inline int check_vector_shrink(const vector_t* const vector, const double threshold) {
/* Calculate the threshold and length. */
size_t current_size = vector->last_element;
size_t current_threshold = (size_t)((vector->length) * (THRESHOLD_WHOLE_VECTOR_C - threshold));
/* Check if it needs to be shrunk. */
return (current_size <= current_threshold) ? CODE_SHRINK_VECTOR_C : CODE_KEEP_VECTOR_C;
}

View File

@ -57,7 +57,10 @@
/* The threshold used to shrink the vector. */
#define THRESHOLD_SHRINK_VECTOR_C 0.25
/* Define the initial index for the last element. */
#define LAST_ELEMENT_EMPTY_INDEX_VECTOR_C -1
#define LAST_ELEMENT_EMPTY_INDEX_VECTOR_C 0
/* Boolean Logic. */
#define TRUE 1
#define FALSE 0
/* Useful typedef for void pointers to make it simpler to deal with. */
@ -73,6 +76,8 @@ typedef struct vector {
size_t element_size;
/* Stores the index of the last used element (inclusive!). */
size_t last_element;
/* Stores whethere or not the vector is empty. */
char empty;
/* Stores a pointer to the array. */
void_ptr *array;
} vector_t;
@ -97,8 +102,10 @@ static inline int copy_vector(vector_t *restrict source, vector_t **restrict des
/* This function frees a vector. */
static inline void free_vector(vector_t *vector, void (*free_function)(const void*));
/* Internal functions. */
/* This function checks if the vector needs to be grown or shrunk. */
static inline int check_size_change_vector(const vector_t* const vector, const double threshold);
/* This function checks if a vector needs to be grown. */
static inline int check_vector_grow(const vector_t* const vector, const double threshold);
/* This function checks if a vector needs to be shrunk. */
static inline int check_vector_shrink(const vector_t* const vector, const double threshold);
/* This function grows the vector, doesn't change the vector on failure. */
static inline int grow_vector(vector_t* const vector);
/* This function shrinks the vector, doesn't change the vector on failure. */