Created
July 11, 2012 03:54
-
-
Save zrbecker/3087880 to your computer and use it in GitHub Desktop.
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
/* | |
* == 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