/* Example: struct * dynamic array, function-initialized, custom vector type */
/* Part of genvector examples (http://repo.hu/projects/genvector) */
#include <stdio.h>
#include "val.h"

/* print the array with a prefix */
static void dump(const char *prefix, vtvalo_t *v)
{
	if (v->array != NULL) {
		int n;
		printf("%-12s", prefix);
		for(n = 0; n < vtvalo_len(v); n++)
			printf(" %s=%.2f", v->array[n].name, v->array[n].val);
		printf("\n");
	}
	else
		printf("%-12s <NULL>\n", prefix);
}

int val_constructor(vtvalo_t *v, val_t *elem)
{
	elem->name = malloc(16);
	strcpy(elem->name, "*BLANK*");
	elem->val = -2.0;
	return 0;
}

void val_destructor(vtvalo_t *v, val_t *elem)
{
	free(elem->name);
	elem->val = -3.0;
}

int val_copy(vtvalo_t *v, val_t *dst, const val_t *src)
{
	dst->name = malloc(strlen(src->name)+1);
	strcpy(dst->name, src->name);
	dst->val = src->val;
	return 0;
}

int main()
{
	int n;
	vtvalo_t a, a2;
	val_t carr[] = {
		{"two",   2.0},
		{"three", 3.0},
		{"four",  4.0}
	};
	val_t carr2[] = {
		{"seven", 7.0},
		{"six",   6.0},
		{"five",  5.0}
	};

	/* Initialize the vectors (to empty, which means the array is not allocated) */
	vtvalo_init(&a);
	a.elem_constructor = val_constructor;
	a.elem_destructor  = val_destructor;
	a.elem_copy        = val_copy;

	vtvalo_init(&a2);
	a2.elem_constructor = val_constructor;
	a2.elem_destructor  = val_destructor;
	a2.elem_copy        = val_copy;

	dump("empty: ", &a);

	/* append 100..109, int by int */
	for(n = 0; n < 10; n++) {
		val_t v = {"fill", 0.0};
		v.val = 100+n;
		/* Use append_len() instead of append() to avoid v copied onto the stack */
		vtvalo_append_len(&a, &v, 1);
	}
	dump("append: ", &a);

	/* append a static array */
	vtvalo_append_len(&a, carr, sizeof(carr)/sizeof(val_t));
	dump("append_len: ", &a);

	/* truncate after 8 elements */
	vtvalo_truncate(&a, 8);
	dump("truncate: ", &a);

	/* Concat two vectors: sort of "s += s2" */
	vtvalo_append_len(&a, carr2, sizeof(carr2)/sizeof(val_t));
	vtvalo_concat(&a, &a2);
	dump("concat: ", &a);

	/* Array is still just an int * array */
	printf("[3] is:      %s=%.2f\n", a.array[3].name, a.array[3].val);

	/* It can be read or written as an int * array, within bounds */
	a.array[5].name = realloc(a.array[5].name, 9);
	strcpy(a.array[5].name, "manual");
	a.array[5].val = 99;
	dump("array asg: ", &a);

	/* Initializing an element beyond current end will create multiple
	   new elements, all initialized using the initialized function */
	{
		val_t v = { "set", 3.14 }; /* this one won't be destructed so no constructor is needed and fields can be static */

		/* NOTE: use set_ptr() over set() so that v doesn't need to be copied onto the stack */
		vtvalo_set_ptr(&a, 15, &v);
		dump("set: ", &a);
	}

	/* Remove a mid-section of the array, 3 elements starting from [2] */
	vtvalo_remove(&a, 2, 3);
	dump("remove: ", &a);

	/* Free memory */
	vtvalo_uninit(&a);
	vtvalo_uninit(&a2);

	return 0;
}
