Started fixing bugs in vector, still not done (check TODO in vector.c).
This commit is contained in:
parent
599b92d77d
commit
913fa38663
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
Loading…
Reference in New Issue