Last active
August 9, 2023 13:24
-
-
Save eurocat2k/66f58fc608f170c98c2f09224e0d0f01 to your computer and use it in GitHub Desktop.
vector data type library for C
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "vector.h" | |
#include <assert.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <stdbool.h> | |
// instance of vector_t | |
struct vector_instance_t { | |
void *data; | |
size_t data_size; | |
int capacity; | |
int length; | |
int err_code; | |
bool initialized; | |
}; | |
// API | |
void _vector_init(vector_ptr_t v, size_t data_size) { | |
assert((v != NULL)); | |
assert(data_size); | |
v->initialized = false; | |
v->capacity = VECTOR_INIT_CAPACITY; | |
v->length = 0; | |
v->data_size = 0; | |
v->err_code = VECTOR_NO_ERROR; | |
if ((v->data = (void *)malloc(data_size * v->capacity)) != NULL) { | |
v->data_size = data_size; | |
v->initialized = true; | |
} else { | |
v->err_code = VECTOR_ERROR_ALLOC; | |
} | |
} | |
// vector new | |
vector_ptr_t vector_new(size_t data_size) { | |
vector_ptr_t v = NULL; | |
if ((v = (vector_ptr_t)calloc(1, sizeof(struct vector_instance_t))) != NULL) { | |
_vector_init(v, data_size); | |
if (v->err_code != VECTOR_NO_ERROR) { | |
free(v); | |
v = NULL; | |
return NULL; | |
} | |
return v; | |
} | |
return NULL; | |
} | |
// | |
void vector_init(vector_ptr_t v, size_t data_size) { | |
assert((v != NULL)); | |
assert(data_size); | |
v->initialized = false; | |
v->capacity = VECTOR_INIT_CAPACITY; | |
v->length = 0; | |
v->data_size = 0; | |
v->err_code = VECTOR_NO_ERROR; | |
if ((v->data = (void *)malloc(data_size * v->capacity)) != NULL) { | |
v->data_size = data_size; | |
v->initialized = true; | |
} else { | |
v->err_code = VECTOR_ERROR_ALLOC; | |
} | |
} | |
// | |
int vector_length(vector_ptr_t v) { | |
assert((v != NULL)); | |
return v->length; | |
} | |
// | |
int vector_capacity(vector_ptr_t v) { | |
assert((v != NULL)); | |
return v->capacity; | |
} | |
// | |
size_t vector_data_size(vector_ptr_t v) { | |
assert((v != NULL)); | |
return v->data_size; | |
} | |
// | |
bool vector_empty(vector_ptr_t v) { | |
assert((v != NULL)); | |
return vector_length(v) == 0; | |
} | |
// | |
int vector_error_code(vector_ptr_t v) { | |
assert(v != NULL); | |
return v->err_code; | |
} | |
// | |
void vector_resize(vector_ptr_t v, int capacity) { | |
assert((v != NULL)); | |
assert(v->initialized); | |
#ifdef DEBUG_ON | |
printf("vector_resize: %d to %d\n", v->capacity, capacity); | |
#endif | |
void *data = NULL; | |
v->err_code = VECTOR_NO_ERROR; | |
if ((data = realloc(v->data, (v->data_size * capacity))) != NULL) { | |
v->data = data; | |
v->capacity = capacity; | |
} else { | |
v->err_code = VECTOR_ERROR_REALLOC; | |
} | |
} | |
// | |
void _vector_resize(vector_ptr_t v) { | |
assert(v != NULL); | |
if (v->length == v->capacity) { | |
v->err_code = VECTOR_NO_ERROR; | |
int cap = v->capacity += v->capacity / 2; | |
void *data = NULL; | |
if ((data = realloc(v->data, v->data_size * cap)) != NULL) { | |
v->data = data; | |
} else { | |
v->err_code = VECTOR_ERROR_REALLOC; | |
} | |
} | |
} | |
// | |
void _vector_add_in(vector_ptr_t v, void *item, size_t pos) { | |
assert(v != NULL); | |
assert(item != NULL); | |
assert(pos <= v->length); | |
_vector_resize(v); // add new space for element if needed | |
if (!vector_error_code(v)) { | |
// no error occurred | |
// move elements to let new element fit in slot at position | |
void *ptr1, *ptr2, *ptr3 = v->data + (pos * v->data_size); | |
for (size_t i = v->length; i > pos; --i) { | |
ptr1 = v->data + (i * v->data_size); | |
ptr2 = v->data + ((i - 1) * v->data_size); | |
memmove(ptr1, (const void*) ptr2, v->data_size); | |
} | |
memmove(ptr3, (const void*)item, v->data_size); | |
v->length += 1; | |
} | |
} | |
// | |
void vector_push_at(vector_ptr_t v, void *item, size_t pos) { | |
assert(v != NULL); | |
assert(item != NULL); | |
assert(pos <= v->length); | |
_vector_add_in(v, item, pos); | |
} | |
// | |
void _vector_delete_in(vector_ptr_t v, size_t pos) { | |
if (pos < v->length) { | |
void *ptr1, *ptr2, *ptr3 = v->data; | |
// move elements | |
for (size_t i = pos; i < v->length - 1; ++i) { | |
ptr1 = ptr3 + (i * v->data_size); | |
ptr2 = ptr3 + ((i + 1) * v->data_size); | |
memmove(ptr1, ptr2, v->data_size); | |
} | |
_vector_resize(v); | |
if (v->err_code == 0) { | |
v->length -= 1; | |
} | |
} | |
} | |
// | |
void vector_delete_at(vector_ptr_t v, size_t pos) { | |
assert(v != NULL); | |
assert(v->initialized); | |
assert(pos); | |
if (v->length && pos < v->length) { | |
_vector_delete_in(v, pos); | |
} | |
} | |
// | |
void vector_delete_back(vector_ptr_t v) { | |
assert(v != NULL); | |
assert(v->initialized); | |
if (v->length) { | |
_vector_delete_in(v, v->length - 1); | |
} | |
} | |
// | |
void vector_delete_front(vector_ptr_t v) { | |
assert(v != NULL); | |
assert(v->initialized); | |
if (v->length) { | |
_vector_delete_in(v, 0); | |
} | |
} | |
// | |
void vector_push_back(vector_ptr_t v, void *item) { | |
assert((v != NULL)); | |
assert(item != NULL); | |
assert(v->initialized); | |
_vector_resize(v); // add new space for element if needed | |
if (v->err_code == 0) { | |
// no error | |
if (v->length == 0) { | |
_vector_add_in(v, item, 0); | |
} else { | |
_vector_add_in(v, item, v->length); | |
} | |
} | |
} | |
// | |
void vector_push_front(vector_ptr_t v, void *item) { | |
assert(v != NULL); | |
assert(item != NULL); | |
assert(v->initialized); | |
_vector_add_in(v, item, 0); | |
} | |
// | |
void _vector_destroy(vector_ptr_t v) { | |
assert(v != NULL); | |
assert(v->initialized); | |
if (v->data != NULL) { | |
free(v->data); | |
v->data = NULL; | |
} | |
v->length = 0; | |
v->capacity = 0; | |
v->err_code = 0; | |
v->initialized = false; | |
} | |
// | |
void vector_destroy(vector_ptr_t *v) { | |
vector_ptr_t _v = *v; | |
_vector_destroy(_v); | |
free(_v); | |
_v = NULL; | |
*v = _v; | |
} | |
// | |
void vector_resize_to_fit(vector_ptr_t v) { | |
assert(v != NULL); | |
assert(v->initialized); | |
if (v->length) { | |
v->err_code = VECTOR_NO_ERROR; | |
void *data = NULL; | |
size_t cap = v->length + 1; | |
if ((data = realloc(v->data, (cap * v->data_size))) != NULL) { | |
v->capacity = cap; | |
v->data = data; | |
} else { | |
v->err_code = VECTOR_ERROR_REALLOC; | |
} | |
} | |
} | |
// | |
void _vector_set_at(vector_ptr_t v, void *item, size_t pos) { | |
if (pos < v->length) { | |
void *ptr = v->data + (pos * v->data_size); | |
memmove(ptr, (const void *)item, v->data_size); | |
} | |
} | |
// | |
void vector_set_at(vector_ptr_t v, void *item, size_t pos) { | |
assert(v != NULL); | |
assert(item != NULL); | |
assert(v->initialized); | |
_vector_set_at(v, item, pos); | |
} | |
// | |
void vector_set_front(vector_ptr_t v, void *item) { | |
assert(v != NULL); | |
assert(item != NULL); | |
assert(v->initialized); | |
_vector_set_at(v, item, 0); | |
} | |
// | |
void vector_set_back(vector_ptr_t v, void *item) { | |
assert(v != NULL); | |
assert(item != NULL); | |
assert(v->initialized); | |
_vector_set_at(v, item, v->length - 1); | |
} | |
// | |
void *_vector_get_at(vector_ptr_t v, size_t pos) { | |
return (v->data + (pos * v->data_size)); | |
} | |
// | |
void *vector_get_at(vector_ptr_t v, size_t pos) { | |
assert(v != NULL); | |
assert(v->initialized); | |
if (pos < v->length) { | |
return (v->data + (pos * v->data_size)); | |
} | |
return NULL; | |
} | |
// | |
void *vector_get_front(vector_ptr_t v) { | |
assert(v != NULL); | |
assert(v->initialized); | |
return _vector_get_at(v, 0); | |
} | |
// | |
void *vector_get_back(vector_ptr_t v) { | |
assert(v != NULL); | |
assert(v->initialized); | |
return _vector_get_at(v, v->length - 1); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef __VECTOR_H__ | |
#define __VECTOR_H__ | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <stdbool.h> | |
#ifdef __cplusplus | |
extern "C" { | |
#endif | |
#define VECTOR_INIT_CAPACITY 4 | |
// define error codes | |
#define VECTOR_NO_ERROR 0 | |
#define VECTOR_ERROR_ALLOC -1 | |
#define VECTOR_ERROR_REALLOC -2 | |
typedef struct vector_instance_t vector_t; | |
typedef vector_t* vector_ptr_t; | |
vector_ptr_t vector_new(size_t); | |
void vector_init(vector_ptr_t, size_t); | |
void vector_destroy(vector_ptr_t *); | |
int vector_error_code(vector_ptr_t); | |
int vector_length(vector_ptr_t); | |
int vector_capacity(vector_ptr_t); | |
bool vector_empty(vector_ptr_t); | |
void vector_resize(vector_ptr_t, int); | |
void vector_resize_to_fit(vector_ptr_t); | |
size_t vector_data_size(vector_ptr_t); | |
void vector_push_back(vector_ptr_t, void *); | |
void vector_push_front(vector_ptr_t, void *); | |
void vector_push_at(vector_ptr_t, void *, size_t); | |
void vector_delete_back(vector_ptr_t); | |
void vector_delete_front(vector_ptr_t); | |
void vector_delete_at(vector_ptr_t, size_t); | |
void *vector_get_at(vector_ptr_t, size_t); | |
void *vector_get_front(vector_ptr_t); | |
void *vector_get_back(vector_ptr_t); | |
void vector_set_at(vector_ptr_t, void *, size_t); | |
void vector_set_front(vector_ptr_t, void *); | |
void vector_set_back(vector_ptr_t, void *); | |
#ifdef __cplusplus | |
} | |
#endif | |
#endif // __VECTOR_H__ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Vector data type and library written for C language
This little C library written to handle vector data type - similar in C++ - the memory management allows to handle item insertions or deletions dynamically.
API
Constructor
Destructor
Destructs the vector data instance - free up memory used by.
Creates vector_ptr_t instance and initializes with VECTOR_INIT_CAPACITY free slots. The vector container data items are empty - no initialized, undefined - do not use them before set them!
Vector attribute setters and getters and aux functions
Vector element manipulations
Sample code for test with integers
main.c
Compile and run
On my machine the result with valgrind looks like this: