// @COMPILECMD gcc $@ -o vector.out
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
	char   * data;
	size_t   element_size;
	size_t   element_count;
} vector_t;

typedef struct {
	int    a;
	int    b;
	char * c;
} example_t;

extern void vector_init(vector_t * vector,
                        size_t     element_size,
                        size_t     element_count);

extern void vector_push(vector_t * vector,
                        void     * data);

extern void vector_pop(vector_t * vector);

extern void * vector_get(vector_t * vector,
                         size_t     element);

extern void vector_set(vector_t * vector,
                       void     * data,
                       size_t     element);

extern void vector_free(vector_t * vector);

extern void example_print(example_t * example);

void vector_init(vector_t * vector,
                 size_t     element_size,
                 size_t     element_count) {
	vector->data          = NULL;
	vector->element_size  = element_size;
	vector->element_count = element_count;

	vector->data = malloc(vector->element_size * vector->element_count);

	if ((! vector->data) && (vector->element_count)) {
		// Handle or output error somehow?
		puts("vector_init");
		exit(EXIT_FAILURE);
	}

	memset(vector->data,
	       0,
	       vector->element_size * vector->element_count);
}

void vector_push(vector_t * vector,
                 void     * data) {
	++vector->element_count;

	vector->data = realloc(vector->data,
	                       vector->element_size * vector->element_count);

	if (! vector->data) {
		// Handle or output error somehow?
		puts("vector_push");
		exit(EXIT_FAILURE);
	}

	memcpy(&vector->data[(vector->element_count - 1) * vector->element_size],
	       data,
	       vector->element_size);
}

void vector_pop(vector_t * vector) {
	(void) vector;
}

void * vector_get(vector_t * vector,
                  size_t     element) {
	if (element >= vector->element_count) {
		// Handle or output error somehow?
		puts("vector_get");
		exit(EXIT_FAILURE);
	}

	return &vector->data[vector->element_size * element];
}

void vector_set(vector_t * vector,
                void     * data,
                size_t     element) {
	if (element >= vector->element_count) {
		// Handle or output error somehow?
		puts("vector_set");
		exit(EXIT_FAILURE);
	}

	memcpy(&vector->data[vector->element_size * element],
	       data,
	       vector->element_size);
}

void vector_free(vector_t * vector) {
	free(vector->data);
}

void example_print(example_t * example) {
	printf("a : %+i\n", example->a);
	printf("b : %+i\n", example->b);
	printf("c : %2s\n", example->c);
}

int main(void) {
	vector_t vector;

	example_t x = { 1, -1, "A" },
	          y = { 2, -2, "B" },
	          z = { 3, -3, "C" };

	vector_init(&vector, sizeof(example_t), 10);

	vector_set(&vector, &x, 0);
	vector_set(&vector, &y, 1);
	vector_set(&vector, &z, 2);

	example_print(vector_get(&vector, 0));
	example_print(vector_get(&vector, 1));
	example_print(vector_get(&vector, 2));

	vector_free(&vector);

	return (EXIT_SUCCESS);
}