summaryrefslogtreecommitdiff
path: root/src/vector.c
blob: 72b2a4f6030e6f8b97b944d7b432d53882a9b8a9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "../include/osm/utils.h"
#include <stdlib.h>
#include <string.h>

#define VECT_MAX_GROW 1024
#define VECT_INIT_CAP 4

/**
 * Initialize a new vector
 */
Vector vect_init(unsigned int elsz)
{
	Vector out = {
		.elsz = elsz,
		.size = VECT_INIT_CAP,
		.count = 0
	};

	out.data = malloc(out.elsz * out.size);

	return out;
}

/**
 * Unexported function for auto-growing the vector
 */
void _vect_grow(Vector *vec)
{
	if (vec->elsz == 0)
	{
		return;
	}

	if (vec->size == 0)
	{
		vec->size = VECT_INIT_CAP;
		vec->data = realloc(vec->data, vec->size * vec->elsz);
		return;
	}

	if (vec->size > VECT_MAX_GROW)
	{
		vec->size += VECT_MAX_GROW;
	}
	else
	{
		vec->size *= 2;
	}

	vec->data = realloc(vec->data, vec->size * vec->elsz);
}

/**
 * Unexported function for auto-shrinking the vector
 */
void _vect_shrink(Vector *vec)
{
	if (vec->size == 1)
	{
		return;
	}

	vec->size /= 2;
	vec->data = realloc(vec->data, vec->size * vec->elsz);
}

/**
 * Push a new element to the end of the vector
 */
void vect_push(Vector *vec, void *el)
{
	memcpy(vec->data + (vec->count * vec->elsz), el, vec->elsz);
	vec->count++;

	if (vec->size == vec->count)
	{
		_vect_grow(vec);
	}
}

/**
 * Pop an element off of the end of the vector
 */
void vect_pop(Vector *vec)
{
	vec->count--;
	
	if (vec->count < vec->size / 3)
	{
		_vect_shrink(vec);
	}
}

void vect_end(Vector *vec)
{
	vec->size = 0;
	vec->count = 0;
	vec->elsz = 0;
	free(vec->data);
	vec->data = NULL;
}