Skip to content

Instantly share code, notes, and snippets.

@dannvix
Created October 8, 2015 14:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save dannvix/6f5988c1e1b99dc91b0d to your computer and use it in GitHub Desktop.
Save dannvix/6f5988c1e1b99dc91b0d to your computer and use it in GitHub Desktop.
Simple std::vector-like container implemented in C99, without error handling and thread-safety
/*
* c99-vector.c
* - Description: Simple std::vector-like container implemented in C99, without error handling and thread-safety
* - Author: Shao-Chung Chen
* - License: CC0
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _c_vector {
size_t capacity;
size_t length;
size_t element_size;
void *buffer;
} c_vector;
c_vector*
c_vector_init(c_vector *c_vector_p, size_t element_size) {
if (!c_vector_p) return NULL;
c_vector_p->capacity = 16;
c_vector_p->length = 0;
c_vector_p->element_size = element_size;
c_vector_p->buffer = malloc(c_vector_p->capacity * element_size);
return c_vector_p;
}
void
c_vector_destroy(c_vector *c_vector_p) {
if (!c_vector_p) return;
free(c_vector_p->buffer);
c_vector_p->capacity = 0;
c_vector_p->length = 0;
c_vector_p->element_size = 0;
c_vector_p->buffer = NULL;
}
size_t
c_vector_capacity(c_vector *c_vector_p) {
if (!c_vector_p) return 0;
return c_vector_p->capacity;
}
size_t
c_vector_length(c_vector *c_vector_p) {
if (!c_vector_p) return 0;
return c_vector_p->length;
}
void
c_vector_clear(c_vector *c_vector_p) {
if (!c_vector_p) return;
c_vector_p->length = 0;
}
void*
c_vector_at(c_vector *c_vector_p, size_t index) {
if (!c_vector_p || index >= c_vector_p->length) return NULL;
return (void*)((char*)c_vector_p->buffer + (index * c_vector_p->element_size));
}
void
c_vector_resize(c_vector *c_vector_p, size_t new_capacity) {
if (!c_vector_p || new_capacity < c_vector_p->length) return;
c_vector_p->capacity = new_capacity;
c_vector_p->buffer = realloc(c_vector_p->buffer, c_vector_p->capacity * c_vector_p->element_size);
}
void*
c_vector_push_back(c_vector *c_vector_p, void* value_p) {
if (!c_vector_p || !value_p) return NULL;
if (c_vector_p->length+1 >= c_vector_p->capacity) {
/* out of capacity, re-allocate with buffer size doubled */
c_vector_resize(c_vector_p, c_vector_p->capacity * 2);
}
++c_vector_p->length;
void *dest_p = c_vector_at(c_vector_p, c_vector_p->length-1);
memcpy(dest_p, value_p, c_vector_p->element_size);
return dest_p;
}
void
c_vector_pop_back(c_vector *c_vector_p) {
if (!c_vector_p || !c_vector_p->length) return;
--c_vector_p->length;
}
void*
c_vector_insert(c_vector *c_vector_p, size_t index, void* value_p) {
if (!c_vector_p || !value_p || index >= c_vector_p->length) return NULL;
if (c_vector_p->length+1 >= c_vector_p->capacity) {
/* out of capacity, re-allocate with buffer size doubled */
c_vector_resize(c_vector_p, c_vector_p->capacity * 2);
}
void *dest_p = c_vector_at(c_vector_p, index);
memmove((void*)((char*)dest_p+c_vector_p->element_size), dest_p, c_vector_p->element_size * (c_vector_p->length - index));
++c_vector_p->length;
memcpy(dest_p, value_p, c_vector_p->element_size);
return dest_p;
}
void
c_vector_erase(c_vector *c_vector_p, size_t index) {
if (!c_vector_p || index >= c_vector_p->length) return;
void *dest_p = c_vector_at(c_vector_p, index);
--c_vector_p->length;
memmove(dest_p, (void*)((char*)dest_p+c_vector_p->element_size), c_vector_p->element_size * (c_vector_p->length - index));
}
typedef struct _c_vector_iterator {
c_vector *c_vector_p;
size_t current_index;
} c_vector_iterator;
c_vector_iterator*
c_vector_iterator_init(c_vector_iterator *iterator_p, c_vector *c_vector_p) {
if (!iterator_p || !c_vector_p) return NULL;
iterator_p->c_vector_p = c_vector_p;
iterator_p->current_index = 0;
return iterator_p;
}
void
c_vector_iterator_destroy(c_vector_iterator *iterator_p) {
/*do nothing*/
}
void*
c_vector_iterator_next(c_vector_iterator *iterator_p) {
c_vector *c_vector_p = iterator_p->c_vector_p;
if (iterator_p->current_index >= c_vector_p->length) return NULL;
void *ret = (void*)((char*)c_vector_p->buffer + (c_vector_p->element_size * iterator_p->current_index));
++iterator_p->current_index;
return ret;
}
int main() {
c_vector v;
c_vector_init(&v, sizeof(int));
printf("v.capacity() = %zu\n", c_vector_capacity(&v));
printf("v.length() = %zu\n", c_vector_length(&v));
for (int i = 0; i < 42; i++) {
c_vector_push_back(&v, (void*)&i);
}
printf("v.length() = %zu\n", c_vector_length(&v));
c_vector_iterator it;
c_vector_iterator_init(&it, &v);
int *num_p = NULL;
while ((num_p = (int*) c_vector_iterator_next(&it))) {
printf("v.next() = %d\n", *num_p);
}
c_vector_iterator_destroy(&it);
c_vector_pop_back(&v);
c_vector_pop_back(&v);
printf("v.capacity() = %zu\n", c_vector_capacity(&v));
printf("v.length() = %zu\n", c_vector_length(&v));
c_vector_resize(&v, 40);
printf("v.capacity() = %zu\n", c_vector_capacity(&v));
printf("v.length() = %zu\n", c_vector_length(&v));
for (int i = 10; i < 16; i++) {
c_vector_insert(&v, c_vector_length(&v)-1, &i);
}
printf("v.capacity() = %zu\n", c_vector_capacity(&v));
printf("v.length() = %zu\n", c_vector_length(&v));
for (size_t i = 0; i < c_vector_length(&v); ++i) {
int *num_p = (int*)c_vector_at(&v, i);
printf("v.at(%zu) = %d\n", i, *num_p);
}
c_vector_erase(&v, 0);
c_vector_erase(&v, 0);
c_vector_erase(&v, 0);
c_vector_erase(&v, 0);
printf("v.capacity() = %zu\n", c_vector_capacity(&v));
printf("v.length() = %zu\n", c_vector_length(&v));
for (size_t i = 0; i < c_vector_length(&v); ++i) {
int *num_p = (int*)c_vector_at(&v, i);
printf("v.at(%zu) = %d\n", i, *num_p);
}
c_vector_clear(&v);
printf("v.capacity() = %zu\n", c_vector_capacity(&v));
printf("v.length() = %zu\n", c_vector_length(&v));
c_vector_destroy(&v);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment