CHORE: Bug fixing. Major changes to bugs and also unit testing
This commit is contained in:
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
+61
-81
@@ -7,42 +7,11 @@
|
||||
|
||||
#include "utils/utils.h"
|
||||
|
||||
/**
|
||||
* @file char.c
|
||||
* @brief Dynamic contiguous array specialization for raw char elements.
|
||||
*
|
||||
* DESIGN CONTRACT:
|
||||
* - RAW BYTE CONTAINER:
|
||||
* This vector manages a sequence of independent 'char' values (raw bytes).
|
||||
* It is NOT a C-string container. Buffers are NEVER null-terminated ('\0').
|
||||
* Passing _vec_char_data() directly to string utilities (e.g., strlen, printf
|
||||
* %s) or treating it as a NUL-terminated string is undefined behavior.
|
||||
*
|
||||
* - ELEMENT VALIDITY & BOUNDS:
|
||||
* Valid elements reside strictly in the half-open range [0, _internal_size).
|
||||
* Slots in the range [_internal_size, _internal_capacity) are spare capacity
|
||||
* and must be treated as uninitialized storage. Any access past
|
||||
* _internal_size - 1 is out of bounds.
|
||||
*
|
||||
* - ERROR HANDLING:
|
||||
* Functions taking an `err_t*` out-parameter require a non-NULL pointer.
|
||||
* On error, appropriate bit flags (defined in utils.h) are bitwise OR-ed into
|
||||
* `err->flags`, and the initial failure site is recorded in `err->origin`.
|
||||
*
|
||||
* - MEMORY OWNERSHIP:
|
||||
* Buffers are heap-allocated via malloc/realloc and owned exclusively by
|
||||
* the vector instance. Use _vec_char_delete() to release resources.
|
||||
*/
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const _VecCharInternal* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
err_t err = ERR_T_INIT;
|
||||
err.flags = ERR_ERR_T_NULL;
|
||||
err.origin = "NULL_CHECK";
|
||||
*status = err;
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
@@ -61,6 +30,10 @@ __null_check(const _VecCharInternal* ptr, err_t* status)
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const char* ptr, err_t* status)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
status->flags |= ERR_BUF_NULL;
|
||||
@@ -71,6 +44,10 @@ __null_check(const char* ptr, err_t* status)
|
||||
size_t
|
||||
__origin_override(err_t* status, char* str)
|
||||
{
|
||||
if (status == nullptr)
|
||||
{
|
||||
return ERR_ERR_T_NULL;
|
||||
}
|
||||
if (status->origin != nullptr)
|
||||
{
|
||||
status->flags |= ERR_ORIGIN_UNALTERABLE;
|
||||
@@ -108,8 +85,13 @@ _vec_char_cpy(const char* src, const size_t src_size, err_t* err)
|
||||
_VecCharInternal self = VEC_INIT;
|
||||
err_t status = ERR_T_INIT;
|
||||
|
||||
if (__null_check(src, &status) != 0)
|
||||
size_t null = __null_check(src, err);
|
||||
if (null != 0)
|
||||
{
|
||||
if (null & ERR_ERR_T_NULL)
|
||||
{
|
||||
return self;
|
||||
}
|
||||
__origin_override(err, "CPY");
|
||||
err->flags |= status.flags;
|
||||
return self;
|
||||
@@ -166,7 +148,7 @@ _vec_char_push_back(_VecCharInternal* ptr, const char val, err_t* err)
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "PUSH_BACK");
|
||||
err->flags |= ERR_BUF_NULL;
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->_internal_arr = res;
|
||||
@@ -216,6 +198,7 @@ _vec_char_pop_back(_VecCharInternal* ptr, err_t* err)
|
||||
if (ptr->_internal_size == 0)
|
||||
{
|
||||
__origin_override(err, "POP_BACK");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -227,7 +210,6 @@ void
|
||||
_vec_char_reserve(_VecCharInternal* ptr, const size_t capacity, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
char* res;
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
if ((status.flags & ERR_VEC_NULL) != 0)
|
||||
@@ -237,6 +219,12 @@ _vec_char_reserve(_VecCharInternal* ptr, const size_t capacity, err_t* err)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (ptr->_internal_max_size < capacity)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_SIZE_OVERFLOW;
|
||||
return;
|
||||
}
|
||||
if (capacity == 0)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
@@ -244,38 +232,19 @@ _vec_char_reserve(_VecCharInternal* ptr, const size_t capacity, err_t* err)
|
||||
return;
|
||||
}
|
||||
|
||||
if ((status.flags & ERR_BUF_NULL) != 0)
|
||||
char* res = realloc(ptr->_internal_arr, capacity * sizeof(char));
|
||||
if (res == nullptr)
|
||||
{
|
||||
res = calloc(capacity, sizeof(char));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->_internal_arr = res;
|
||||
ptr->_internal_capacity = capacity;
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
res = realloc(ptr->_internal_arr, capacity * sizeof(char));
|
||||
if (res == nullptr)
|
||||
{
|
||||
__origin_override(err, "RESERVE");
|
||||
err->flags |= ERR_ALLOC_FAIL;
|
||||
return;
|
||||
}
|
||||
ptr->_internal_arr = res;
|
||||
if (ptr->_internal_size > capacity)
|
||||
{
|
||||
memset(&ptr->_internal_arr[capacity], 0,
|
||||
ptr->_internal_size - capacity);
|
||||
ptr->_internal_size = capacity;
|
||||
}
|
||||
}
|
||||
ptr->_internal_arr = res;
|
||||
ptr->_internal_capacity = capacity;
|
||||
if (ptr->_internal_size > capacity)
|
||||
{
|
||||
ptr->_internal_size = capacity;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -283,7 +252,6 @@ void
|
||||
_vec_char_shrink_to_fit(_VecCharInternal* ptr, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if (__null_check(ptr, &status) != 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
@@ -292,25 +260,27 @@ _vec_char_shrink_to_fit(_VecCharInternal* ptr, err_t* err)
|
||||
}
|
||||
if (ptr->_internal_size == 0)
|
||||
{
|
||||
__origin_override(err, "SHRINK_TO_FIT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return;
|
||||
}
|
||||
return _vec_char_reserve(ptr, ptr->_internal_size, err);
|
||||
_vec_char_reserve(ptr, ptr->_internal_size, err);
|
||||
}
|
||||
|
||||
void
|
||||
_vec_char_swap(_VecCharInternal* ptr1, _VecCharInternal* ptr2, err_t* err)
|
||||
_vec_char_swap(_VecCharInternal* ptr_a, _VecCharInternal* ptr_b, err_t* err)
|
||||
{
|
||||
err_t status_1 = ERR_T_INIT, status_2 = ERR_T_INIT;
|
||||
if ((__null_check(ptr1, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||
(__null_check(ptr2, &status_2) & ERR_VEC_NULL) != 0)
|
||||
if ((__null_check(ptr_a, &status_1) & ERR_VEC_NULL) != 0 ||
|
||||
(__null_check(ptr_b, &status_2) & ERR_VEC_NULL) != 0)
|
||||
{
|
||||
__origin_override(err, "SWAP");
|
||||
err->flags |= ERR_VEC_NULL;
|
||||
return;
|
||||
}
|
||||
_VecCharInternal self = *ptr1;
|
||||
*ptr1 = *ptr2;
|
||||
*ptr2 = self;
|
||||
_VecCharInternal self = *ptr_a;
|
||||
*ptr_a = *ptr_b;
|
||||
*ptr_b = self;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -444,6 +414,12 @@ _vec_char_end(const _VecCharInternal* ptr, err_t* err)
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
}
|
||||
if (ptr->_internal_size == 0)
|
||||
{
|
||||
__origin_override(err, "END");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
return status.flags;
|
||||
}
|
||||
return (size_t)(ptr->_internal_size - 1);
|
||||
}
|
||||
|
||||
@@ -455,7 +431,7 @@ _vec_char_front(const _VecCharInternal* ptr, err_t* err)
|
||||
{
|
||||
__origin_override(err, "FRONT");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
return -1;
|
||||
}
|
||||
if (_vec_char_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
@@ -473,7 +449,7 @@ _vec_char_back(const _VecCharInternal* ptr, err_t* err)
|
||||
{
|
||||
__origin_override(err, "BACK");
|
||||
err->flags |= status.flags;
|
||||
return status.flags;
|
||||
return -1;
|
||||
}
|
||||
if (_vec_char_at(ptr, 0, err) == nullptr)
|
||||
{
|
||||
@@ -543,7 +519,7 @@ _vec_char_erase(_VecCharInternal* ptr, const size_t iter_start,
|
||||
memmove(&ptr->_internal_arr[iter_start], &ptr->_internal_arr[iter_end],
|
||||
(ptr->_internal_size - iter_end) * sizeof(char));
|
||||
memset(&ptr->_internal_arr[ptr->_internal_size - diff], 0,
|
||||
sizeof(char) * ptr->_internal_size);
|
||||
sizeof(char) * diff);
|
||||
ptr->_internal_size -= diff;
|
||||
return;
|
||||
}
|
||||
@@ -629,12 +605,13 @@ _vec_char_resize(_VecCharInternal* ptr, const size_t size, err_t* err)
|
||||
}
|
||||
if (size < ptr->_internal_size)
|
||||
{
|
||||
memset(&ptr->_internal_arr[size], 0, ptr->_internal_size);
|
||||
memset(&ptr->_internal_arr[size], 0,
|
||||
ptr->_internal_size - size);
|
||||
}
|
||||
if (ptr->_internal_size < size && size <= ptr->_internal_capacity)
|
||||
{
|
||||
memset(&ptr->_internal_arr[ptr->_internal_size], 0,
|
||||
ptr->_internal_arr[size]);
|
||||
size - ptr->_internal_size);
|
||||
}
|
||||
ptr->_internal_size = size;
|
||||
return;
|
||||
@@ -715,12 +692,13 @@ _vec_char_resize(_VecCharInternal* ptr, const size_t size, const char val,
|
||||
}
|
||||
if (size < ptr->_internal_size)
|
||||
{
|
||||
memset(&ptr->_internal_arr[size], val, ptr->_internal_size);
|
||||
memset(&ptr->_internal_arr[size], val,
|
||||
ptr->_internal_size - size);
|
||||
}
|
||||
if (ptr->_internal_size < size && size <= ptr->_internal_capacity)
|
||||
{
|
||||
memset(&ptr->_internal_arr[ptr->_internal_size], val,
|
||||
ptr->_internal_arr[size]);
|
||||
size - ptr->_internal_size);
|
||||
}
|
||||
ptr->_internal_size = size;
|
||||
return;
|
||||
@@ -767,13 +745,13 @@ _vec_char_assign(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
||||
}
|
||||
for (size_t i = iter_start; i < iter_end; i++)
|
||||
{
|
||||
if (_vec_char_at(iterator, i, &status) != nullptr)
|
||||
char* res = _vec_char_at(iterator, i, &status);
|
||||
if (res == nullptr)
|
||||
{
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
_vec_char_push_back(ptr, *_vec_char_at(iterator, i, &status),
|
||||
&status);
|
||||
_vec_char_push_back(ptr, *res, &status);
|
||||
if (status.flags != 0)
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
@@ -793,6 +771,7 @@ _vec_char_assign(_VecCharInternal* ptr, const size_t amount, const char val,
|
||||
{
|
||||
__origin_override(err, "ASSIGN");
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (amount == 0)
|
||||
{
|
||||
@@ -888,6 +867,7 @@ _vec_char_insert(_VecCharInternal* ptr, const size_t iter, const size_t amount,
|
||||
const char val, err_t* err)
|
||||
{
|
||||
err_t status = ERR_T_INIT;
|
||||
__null_check(ptr, &status);
|
||||
if ((status.flags & (ERR_VEC_NULL | ERR_BUF_NULL)) != 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
@@ -900,7 +880,7 @@ _vec_char_insert(_VecCharInternal* ptr, const size_t iter, const size_t amount,
|
||||
err->flags |= ERR_OUT_OF_BOUNDS;
|
||||
return;
|
||||
}
|
||||
if (amount <= 0)
|
||||
if (amount == 0)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
err->flags |= ERR_SIZE_ZERO;
|
||||
@@ -933,7 +913,7 @@ _vec_char_insert(_VecCharInternal* ptr, const _VecCharInternal* iterator,
|
||||
err->flags |= status.flags;
|
||||
return;
|
||||
}
|
||||
if (iter_end > iter_start || iter_end > iterator->_internal_size ||
|
||||
if (iter_end <= iter_start || iter_end > iterator->_internal_size ||
|
||||
iter > ptr->_internal_size)
|
||||
{
|
||||
__origin_override(err, "INSERT");
|
||||
|
||||
+10
-1
@@ -13,6 +13,15 @@ typedef struct
|
||||
size_t _internal_max_size;
|
||||
} _VecCharInternal;
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const _VecCharInternal* ptr, err_t* status);
|
||||
|
||||
__attribute__((overloadable)) size_t
|
||||
__null_check(const char* ptr, err_t* status);
|
||||
|
||||
size_t
|
||||
__origin_override(err_t* status, char* str);
|
||||
|
||||
void
|
||||
_vec_char_print_vec(const _VecCharInternal* ptr, err_t* err);
|
||||
|
||||
@@ -32,7 +41,7 @@ void
|
||||
_vec_char_shrink_to_fit(_VecCharInternal* ptr, err_t* err);
|
||||
|
||||
void
|
||||
_vec_char_swap(_VecCharInternal* ptr, _VecCharInternal* ptr_other, err_t* err);
|
||||
_vec_char_swap(_VecCharInternal* ptr_a, _VecCharInternal* ptr_b, err_t* err);
|
||||
|
||||
const char*
|
||||
_vec_char_data(const _VecCharInternal* ptr, err_t* err);
|
||||
|
||||
@@ -12,7 +12,7 @@ vec_get_error_desc(ERROR_CODES err)
|
||||
ERROR_LIST(X)
|
||||
#undef X
|
||||
default:
|
||||
"Unknown";
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -34,8 +34,8 @@ main()
|
||||
//
|
||||
// Your pop back is a great example of how to handle it and is a clean
|
||||
// if statement as a header to all functions.
|
||||
char res[4] = { 'a', 'b', 'c', 'd' };
|
||||
err_t status = ERR_T_INIT, err = ERR_T_INIT;
|
||||
// char res[4] = { 'a', 'b', 'c', 'd' };
|
||||
err_t status = ERR_T_INIT;
|
||||
status.flags |= ERR_BUF_NULL | ERR_VEC_NULL | ERR_STR_NULL;
|
||||
|
||||
unsigned int mask = 0;
|
||||
|
||||
Reference in New Issue
Block a user