Skip to content

Instantly share code, notes, and snippets.

@zrbecker
Created July 11, 2012 03:54
Show Gist options
  • Save zrbecker/3087880 to your computer and use it in GitHub Desktop.
Save zrbecker/3087880 to your computer and use it in GitHub Desktop.
/*
* == Altered ==
* assign() is overloaded in c++. Changed assign(n, u) to
* assign_val(n, u);
*
* The insert and erase function use index instead of iterator
* to determine where stuff is inserted/erased
*
* == Not implemented ==
* any operator overloading, obviously
*
* operator= is done by the member function copy()
*
* rbegin(), rend(), max_size(), get_allocator(), swap()
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define c_vector(T) c_vector_##T
#define c_vector_create(T) c_vector_create_##T
#define c_vector_destroy(T) c_vector_destroy_##T
#define c_vector_declarations(T) \
/* Structure Information */ \
typedef struct _c_vector_##T c_vector_##T; \
\
struct _c_vector_##T { \
size_t _size; \
size_t _capacity; \
T *_data; \
\
c_vector_##T* (*copy)(c_vector_##T *self); \
\
/* Iterators */ \
T* (*begin)(c_vector_##T *self); \
T* (*end)(c_vector_##T *self); \
\
/* Capacity */ \
size_t (*size)(c_vector_##T *self); \
void (*resize)(c_vector_##T *self, size_t size, T c); \
size_t (*capacity)(c_vector_##T *self); \
int (*empty)(c_vector_##T *self); \
void (*reserve)(c_vector_##T *self, size_t n); \
\
/* Element Access */ \
T (*at)(c_vector_##T *self, size_t n); \
T (*front)(c_vector_##T *self); \
T (*back)(c_vector_##T *self); \
\
/* Modifiers */ \
void (*assign)(c_vector_##T *self, T *first, T *last); \
void (*assign_val)(c_vector_##T *self, size_t n, T value); \
void (*push_back)(c_vector_##T *self, T value); \
void (*pop_back)(c_vector_##T *self); \
void (*insert)(c_vector_##T *self, size_t pos, T value); \
void (*insert_many)(c_vector_##T *self, size_t pos, size_t n, T value); \
void (*insert_range)(c_vector_##T *self, size_t pos, T *first, T *last); \
void (*erase)(c_vector_##T *self, size_t pos); \
void (*erase_many)(c_vector_##T *self, size_t pos, size_t n); \
void (*clear)(c_vector_##T *self); \
}; \
\
/* Static function declarations. */ \
c_vector_##T *c_vector_create_##T(); \
void c_vector_destroy_##T(c_vector_##T *v); \
\
/* Member function declarations. */ \
c_vector_##T* c_vector_copy_##T(c_vector_##T *self); \
\
T* c_vector_begin_##T(c_vector_##T *self); \
T* c_vector_end_##T(c_vector_##T *self); \
\
size_t c_vector_size_##T(c_vector_##T *self); \
void c_vector_resize_##T(c_vector_##T *self, size_t size, T c); \
size_t c_vector_capacity_##T(c_vector_##T *self); \
int c_vector_empty_##T(c_vector_##T *self); \
void c_vector_reserve_##T(c_vector_##T *self, size_t n); \
\
T c_vector_at_##T(c_vector_##T *self, size_t n); \
T c_vector_front_##T(c_vector_##T *self); \
T c_vector_back_##T(c_vector_##T *self); \
\
void c_vector_assign_##T(c_vector_##T *self, T *first, T *last); \
void c_vector_assign_val_##T(c_vector_##T *self, size_t n, T value); \
void c_vector_push_back_##T(c_vector_##T *self, T value); \
void c_vector_pop_back_##T(c_vector_##T *self); \
void c_vector_insert_##T(c_vector_##T *self, size_t pos, T value); \
void c_vector_insert_many_##T(c_vector_##T *self, \
size_t pos, size_t n, T value); \
void c_vector_insert_range_##T(c_vector_##T *self, \
size_t pos, T *first, T *last); \
void c_vector_erase_##T(c_vector_##T *self, size_t pos); \
void c_vector_erase_many_##T(c_vector_##T *self, size_t pos, size_t n); \
void c_vector_clear_##T(c_vector_##T *self);
#define c_vector_definitions(T) \
/* Static function definitions */ \
c_vector_##T *c_vector_create_##T() { \
c_vector_##T *v = malloc(sizeof(c_vector_##T)); \
\
v->_size = 0; \
v->_capacity = 0; \
v->_data = NULL; \
\
v->copy = c_vector_copy_##T; \
\
v->begin = c_vector_begin_##T; \
v->end = c_vector_end_##T; \
\
v->size = c_vector_size_##T; \
v->resize = c_vector_resize_##T; \
v->capacity = c_vector_capacity_##T; \
v->empty = c_vector_empty_##T; \
v->reserve = c_vector_reserve_##T; \
\
v->at = c_vector_at_##T; \
v->front = c_vector_front_##T; \
v->back = c_vector_back_##T; \
\
v->assign = c_vector_assign_##T; \
v->assign_val = c_vector_assign_val_##T; \
v->push_back = c_vector_push_back_##T; \
v->pop_back = c_vector_pop_back_##T; \
v->insert = c_vector_insert_##T; \
v->insert_many = c_vector_insert_many_##T; \
v->insert_range = c_vector_insert_range_##T; \
v->erase = c_vector_erase_##T; \
v->erase_many = c_vector_erase_many_##T; \
v->clear = c_vector_clear_##T; \
\
return v; \
} \
\
void c_vector_destroy_##T(c_vector_##T *v) { \
if (v->_data == NULL) \
free(v->_data); \
free(v); \
} \
\
/* Member function definitions */ \
c_vector_##T* c_vector_copy_##T(c_vector_##T *self) { \
c_vector_##T *copy = c_vector_create_##T(); \
copy->reserve(self, self->_capacity); \
copy->_size = self->_size; \
memcpy(copy->_data, self->_data, \
copy->_capacity * sizeof(c_vector_##T)); \
return copy; \
} \
\
T* c_vector_begin_##T(c_vector_##T *self) { \
return self->_data; \
} \
\
T* c_vector_end_##T(c_vector_##T *self) { \
return self->_data + self->_size; \
} \
\
size_t c_vector_size_##T(c_vector_##T *self) { \
return self->_size; \
} \
\
void c_vector_resize_##T(c_vector_##T *self, size_t size, T c) { \
if (size > self->_capacity) \
self->reserve(self, size); \
if (size <= self->_size) \
self->_size = size; \
else { \
while (self->_size < size) \
self->push_back(self, c); \
} \
} \
\
size_t c_vector_capacity_##T(c_vector_##T *self) { \
return self->_capacity; \
} \
\
int c_vector_empty_##T(c_vector_##T *self) { \
return self->_size == 0; \
} \
\
void c_vector_reserve_##T(c_vector_##T *self, size_t n) { \
if (n > self->_size) { \
self->_capacity = n; \
self->_data = realloc(self->_data, \
self->_capacity * sizeof(T)); \
} \
} \
\
T c_vector_at_##T(c_vector_##T *self, size_t i) { \
return self->_data[i]; \
} \
\
T c_vector_front_##T(c_vector_##T *self) { \
return self->_data[0]; \
} \
\
T c_vector_back_##T(c_vector_##T *self) { \
return self->_data[self->_size - 1]; \
} \
\
void c_vector_assign_##T(c_vector_##T *self, T *first, T *last) { \
self->reserve(self, last - first); \
memcpy(self->_data, first, last - first); \
} \
\
void c_vector_assign_val_##T(c_vector_##T *self, size_t n, T value) { \
self->reserve(self, n); \
memset(self->_data, value, n); \
} \
\
void c_vector_push_back_##T(c_vector_##T *self, T value) { \
if (self->_size >= self->_capacity) { \
if (self->_capacity) \
self->reserve(self, self->_capacity * 2); \
else \
self->reserve(self, 10); \
} \
self->_data[self->_size++] = value; \
} \
\
void c_vector_pop_back_##T(c_vector_##T *self) { \
if (self->_size > 0) \
self->_size--; \
if (self->_size < self->_capacity / 2) \
self->reserve(self, self->_capacity / 2); \
} \
\
void c_vector_insert_##T(c_vector_##T *self, size_t pos, T value) { \
if (self->_size >= self->_capacity) \
self->reserve(self, self->_capacity * 2); \
memmove(self->_data + pos + 1, \
self->_data + pos, \
self->_size - pos); \
self->_data[pos] = value; \
self->_size++; \
} \
\
void c_vector_insert_many_##T(c_vector_##T *self, \
size_t pos, size_t n, T value) { \
if (self->_size + n > self->_capacity) \
self->reserve(self, self->_size + n); \
memmove(self->_data + pos + n, \
self->_data + pos, \
self->_size - pos); \
memset(self->_data + pos, value, n); \
self->_size += n; \
} \
\
void c_vector_insert_range_##T(c_vector_##T *self, \
size_t pos, T *first, T *last) { \
int n = last - first; \
if (self->_size + n > self->_capacity) \
self->reserve(self, self->_size + n); \
memmove(self->_data + pos + n, \
self->_data + pos, \
self->_size - pos); \
memcpy(self->_data + pos, first, n); \
self->size += n; \
} \
\
void c_vector_erase_##T(c_vector_##T *self, size_t pos) { \
self->_size = pos; \
self->reserve(self, pos); \
} \
\
void c_vector_erase_many_##T(c_vector_##T *self, size_t pos, size_t n) { \
memmove(self->_data + pos, \
self->_data + pos + n, \
self->_size - pos); \
self->_size -= n; \
self->reserve(self, self->_size); \
} \
\
void c_vector_clear_##T(c_vector_##T *self) { \
self->_size = 0; \
self->reserve(self, 10); \
}
#define c_vector_both(T) \
c_vector_declarations(T) \
c_vector_definitions(T)
c_vector_both(int);
c_vector_both(double);
int main() {
// vector of ints
c_vector(int) *v1 = c_vector_create(int)();
v1->push_back(v1, 1);
v1->push_back(v1, 2);
v1->push_back(v1, 3);
v1->push_back(v1, 4);
v1->push_back(v1, 5);
v1->resize(v1, 10, 5);
printf("front: %d back: %d\n", v1->front(v1), v1->back(v1));
printf("size: %lu capacity: %lu\n", v1->size(v1), v1->capacity(v1));
int *it1;
for (it1 = v1->begin(v1); it1 != v1->end(v1); ++it1)
printf("%d ", *it1);
printf("\n");
c_vector_destroy(int)(v1);
// vector of doubles
c_vector(double) *v2 = c_vector_create(double)();
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
v2->push_back(v2, 1.23);
printf("size: %lu capacity: %lu\n", v2->size(v2), v2->capacity(v2));
int i;
for (i = 0; i < v2->size(v2); ++i)
printf("%f ", v2->at(v2, i));
printf("\n");
c_vector(double) *v3 = v2->copy(v2);
v3->resize(v3, 64, 3.14);
printf("size: %lu capacity: %lu\n", v3->size(v3), v3->capacity(v3));
for (i = 0; i < v3->size(v3); ++i)
printf("%f ", v3->at(v3, i));
printf("\n");
if (v3->empty(v3))
printf("v4 is empty.\n");
else
printf("v3 is not empty.\n");
c_vector(double) *v4 = c_vector_create(double)();
if (v4->empty(v4))
printf("v4 is empty.\n");
else
printf("v3 is not empty.\n");
c_vector_destroy(double)(v2);
c_vector_destroy(double)(v3);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment