Created
October 8, 2015 14:57
-
-
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
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
/* | |
* 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