1
0
Fork 0
libfort/src/vector.c

223 lines
5.2 KiB
C
Raw Normal View History

2018-01-17 19:22:57 +01:00
#include "vector.h"
#include <assert.h>
#include <string.h>
2018-01-17 19:22:57 +01:00
/*****************************************************************************
* VECTOR IMPLEMENTATIONS
* ***************************************************************************/
2018-03-31 12:33:37 +02:00
struct vector {
2018-01-17 19:22:57 +01:00
size_t m_size;
void *m_data;
size_t m_capacity;
size_t m_item_size;
};
static int vector_reallocate_(vector_t *vector, size_t new_capacity)
{
assert(vector);
assert(new_capacity > vector->m_capacity);
size_t new_size = new_capacity * vector->m_item_size;
2018-04-01 18:10:43 +02:00
vector->m_data = F_REALLOC(vector->m_data, new_size);
2018-01-17 19:22:57 +01:00
if (vector->m_data == NULL)
return -1;
return 0;
}
/* ------------ Constructors & Destructors ----------------------------- */
2018-03-31 12:33:37 +02:00
vector_t *create_vector(size_t item_size, size_t capacity)
2018-01-17 19:22:57 +01:00
{
2018-04-01 18:10:43 +02:00
vector_t *vector = (vector_t *)F_MALLOC(sizeof(vector_t));
2018-01-17 19:22:57 +01:00
if (vector == NULL) {
SYS_LOG_ERROR("Failed to allocate memory for asock vector");
return NULL;
}
size_t init_size = MAX(item_size * capacity, 1);
2018-04-01 18:10:43 +02:00
vector->m_data = F_MALLOC(init_size);
2018-01-17 19:22:57 +01:00
if (vector->m_data == NULL) {
SYS_LOG_ERROR("Failed to allocate memory for asock vector inern. buffer");
2018-04-01 18:10:43 +02:00
F_FREE(vector);
2018-01-17 19:22:57 +01:00
return NULL;
}
vector->m_size = 0;
vector->m_capacity = capacity;
vector->m_item_size = item_size;
return vector;
}
2018-03-31 12:33:37 +02:00
void destroy_vector(vector_t *vector)
2018-01-17 19:22:57 +01:00
{
assert(vector);
2018-04-01 18:10:43 +02:00
F_FREE(vector->m_data);
F_FREE(vector);
2018-01-17 19:22:57 +01:00
}
2018-03-31 12:33:37 +02:00
vector_t *copy_vector(vector_t *v)
2018-02-25 09:39:41 +01:00
{
if (v == NULL)
return NULL;
2018-03-31 12:33:37 +02:00
vector_t *new_vector = create_vector(v->m_item_size, v->m_capacity);
2018-02-25 09:39:41 +01:00
if (new_vector == NULL)
return NULL;
memcpy(new_vector->m_data, v->m_data, v->m_item_size * v->m_size);
new_vector->m_size = v->m_size ;
new_vector->m_item_size = v->m_item_size ;
return new_vector;
}
2018-01-17 19:22:57 +01:00
/* ----------- Nonmodifying functions --------------------------------- */
2018-03-31 12:33:37 +02:00
size_t vector_size(const vector_t *vector)
2018-01-17 19:22:57 +01:00
{
assert(vector);
return vector->m_size;
}
2018-03-31 12:33:37 +02:00
size_t vector_capacity(const vector_t *vector)
2018-01-17 19:22:57 +01:00
{
assert(vector);
return vector->m_capacity;
}
2018-03-31 12:33:37 +02:00
size_t vector_index_of(const vector_t *vector, const void *item)
2018-01-17 19:22:57 +01:00
{
assert(vector);
assert(item);
2018-03-09 10:44:16 +01:00
size_t i = 0;
for (i = 0; i < vector->m_size; ++i) {
2018-03-31 12:33:37 +02:00
void *data_pos = (char *)vector->m_data + i * vector->m_item_size;
2018-01-17 19:22:57 +01:00
if (memcmp(data_pos, item, vector->m_item_size) == 0) {
return i;
}
}
return INVALID_VEC_INDEX;
}
/* ----------- Modifying functions ------------------------------------- */
2018-03-31 12:33:37 +02:00
int vector_push(vector_t *vector, const void *item)
2018-01-17 19:22:57 +01:00
{
assert(vector);
assert(item);
if (vector->m_size == vector->m_capacity) {
if (vector_reallocate_(vector, vector->m_capacity * 2) == -1)
2018-03-19 21:07:18 +01:00
return FT_ERROR;
2018-01-17 19:22:57 +01:00
vector->m_capacity = vector->m_capacity * 2;
}
ptrdiff_t deviation = vector->m_size * vector->m_item_size;
2018-03-31 12:33:37 +02:00
memcpy((char *)vector->m_data + deviation, item, vector->m_item_size);
2018-01-17 19:22:57 +01:00
++(vector->m_size);
2018-03-19 21:07:18 +01:00
return FT_SUCCESS;
2018-01-17 19:22:57 +01:00
}
int vector_erase(vector_t *vector, size_t index)
{
assert(vector);
if (vector->m_size == 0 || index >= vector->m_size)
2018-03-19 21:07:18 +01:00
return FT_ERROR;
2018-01-17 19:22:57 +01:00
2018-03-31 12:33:37 +02:00
memmove((char *)vector->m_data + vector->m_item_size * index,
(char *)vector->m_data + vector->m_item_size * (index + 1),
2018-01-17 19:22:57 +01:00
(vector->m_size - 1 - index) * vector->m_item_size);
vector->m_size--;
2018-03-19 21:07:18 +01:00
return FT_SUCCESS;
2018-01-17 19:22:57 +01:00
}
void vector_clear(vector_t *vector)
{
vector->m_size = 0;
}
2018-02-25 09:39:41 +01:00
const void *vector_at_c(const vector_t *vector, size_t index)
{
if (index >= vector->m_size)
return NULL;
2018-03-31 12:33:37 +02:00
return (char *)vector->m_data + index * vector->m_item_size;
2018-02-25 09:39:41 +01:00
}
2018-01-17 19:22:57 +01:00
void *vector_at(vector_t *vector, size_t index)
{
if (index >= vector->m_size)
return NULL;
2018-03-31 12:33:37 +02:00
return (char *)vector->m_data + index * vector->m_item_size;
2018-01-17 19:22:57 +01:00
}
2018-04-22 20:42:22 +02:00
fort_status_t vector_swap(vector_t *cur_vec, vector_t *mv_vec, size_t pos)
{
assert(cur_vec);
assert(mv_vec);
2018-04-22 20:49:36 +02:00
assert(cur_vec != mv_vec);
2018-04-22 20:42:22 +02:00
assert(cur_vec->m_item_size == mv_vec->m_item_size);
size_t cur_sz = vector_size(cur_vec);
size_t mv_sz = vector_size(mv_vec);
if (mv_sz == 0) {
return FT_SUCCESS;
}
size_t min_targ_size = pos + mv_sz;
2018-05-12 11:45:42 +02:00
if (vector_capacity(cur_vec) < min_targ_size) {
2018-04-22 20:42:22 +02:00
if (vector_reallocate_(cur_vec, min_targ_size) == -1)
return FT_ERROR;
cur_vec->m_capacity = min_targ_size;
}
ptrdiff_t deviation = pos * cur_vec->m_item_size;
void *tmp = NULL;
size_t new_mv_sz = 0;
if (cur_sz > pos) {
new_mv_sz = MIN(cur_sz - pos, mv_sz);
tmp = F_MALLOC(cur_vec->m_item_size * new_mv_sz);
if (tmp == NULL) {
return FT_MEMORY_ERROR;
}
}
2018-05-12 12:09:07 +02:00
if (tmp) {
memcpy(tmp,
(char *)cur_vec->m_data + deviation,
cur_vec->m_item_size * new_mv_sz);
}
2018-04-22 20:49:36 +02:00
memcpy((char *)cur_vec->m_data + deviation,
2018-04-22 20:42:22 +02:00
mv_vec->m_data,
cur_vec->m_item_size * mv_sz);
2018-05-12 12:09:07 +02:00
if (tmp) {
memcpy(mv_vec->m_data,
tmp,
cur_vec->m_item_size * new_mv_sz);
}
2018-04-22 20:42:22 +02:00
2018-05-12 11:45:42 +02:00
cur_vec->m_size = MAX(cur_vec->m_size, min_targ_size);
2018-04-22 20:42:22 +02:00
mv_vec->m_size = new_mv_sz;
F_FREE(tmp);
return FT_SUCCESS;
}
2018-01-17 19:22:57 +01:00