#include <stdlib.h>
#include <stdio.h>
struct foo
{
int bar;
double baz;
};
struct vector
{
char* beg;
char* last;
char* end;
size_t eltsiz;
};
#define VECTOR_MIN_CAPACITY 2
struct vector* vector_create(size_t eltsiz)
{
struct vector
* ret
= malloc(sizeof(struct vector
));
ret
->beg
= ret
->last
= malloc(eltsiz
* VECTOR_MIN_CAPACITY
); ret->end = ret->beg + eltsiz * VECTOR_MIN_CAPACITY;
ret->eltsiz = eltsiz;
return ret;
}
void vector_free(struct vector* vec)
{
return;
}
void* vector_push(struct vector* vec)
{
if(vec->last == vec->end) {
size_t space_occupied = vec->last - vec->beg;
vec
->beg
= realloc(vec
->beg
, 2*space_occupied
); vec->last = vec->beg + space_occupied;
vec->end = vec->beg + 2*space_occupied;
}
char* ret = vec->last;
vec->last += vec->eltsiz;
return ret;
}
// UB if overflow.
void* vector_get(struct vector* vec, size_t index)
{
return vec->beg + index*vec->eltsiz;
}
// UB if called on an empty vector.
void vector_pop(struct vector* vec)
{
vec->last -= vec->eltsiz;
size_t space_occupied = vec->last - vec->beg;
if(space_occupied <= (vec->end-vec->beg)/4 &&
space_occupied >= vec->eltsiz*VECTOR_MIN_CAPACITY) {
vec
->beg
= realloc(vec
->beg
, 2*space_occupied
); vec->last = vec->beg + space_occupied;
vec->end = vec->beg + 2*space_occupied;
}
return;
}
int main()
{
struct foo sf1 = {.bar = 5, .baz = 15.51}; // May be safely copied.
struct vector* vec1 = vector_create(sizeof(struct foo));
// sf1 is copied, vector stores the struct itself
// rather than a pointer to this struct.
*(struct foo*)vector_push(vec1) = sf1;
*(struct foo*)vector_push(vec1) = (struct foo){.bar = -3, .baz = 100.01};
// Last element is uninitialized.
vector_push(vec1);
printf("%d\n", ((struct foo
*)vector_get
(vec1
, 1))->bar
);
struct foo sf2 = {.bar = 2, .baz = -23.32}; // Mustn't be copied!
struct vector* vec2 = vector_create(sizeof(struct foo*));
// I avoid copying sf2, vector stores pointers to the struct
// rather than the struct itself
*(struct foo**)vector_push(vec2) = &sf2;
*(struct foo
**)vector_push
(vec2
) = malloc(sizeof(struct foo
)); **(struct foo**)vector_get(vec2, 1) = (struct foo){.bar = -4, .baz = -3.2};
// Last element is NULL.
*(struct foo**)vector_push(vec2) = NULL;
printf("%d\n", (*(struct foo
**)vector_get
(vec2
, 1))->bar
);
return 0;
}