vector.c 3.31 KB
Newer Older
Swann Perarnau's avatar
Swann Perarnau committed
1
2
3
4
5
6
7
8
9
10
/*******************************************************************************
 * Copyright 2019 UChicago Argonne, LLC.
 * (c.f. AUTHORS, LICENSE)
 *
 * This file is part of the AML project.
 * For more info, see https://xgitlab.cels.anl.gov/argo/aml
 *
 * SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/

11
#include "aml.h"
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <assert.h>
#include <errno.h>

/*******************************************************************************
 * Vector type:
 * generic vector of elements, with contiguous allocation: elements are part of
 * the vector.
 * This type supports one unusual feature: elements must contain an int key, at
 * a static offset, and this key as configurable "null" value.
 ******************************************************************************/

int aml_vector_resize(struct aml_vector *vec, size_t newsize)
{
	assert(vec != NULL);
	/* we don't shrink */
27
	if (vec->nbelems > newsize)
28
29
30
31
		return 0;

	vec->ptr = realloc(vec->ptr, newsize * vec->sz);
	assert(vec->ptr != NULL);
32
	for (size_t i = vec->nbelems; i < newsize; i++) {
33
34
35
36
37
38
39
		int *k = AML_VECTOR_KEY_P(vec, i);
		*k = vec->na;
	}
	vec->nbelems = newsize;
	return 0;
}

40
size_t aml_vector_size(const struct aml_vector *vec)
41
42
43
44
45
46
47
48
49
{
	assert(vec != NULL);
	return vec->nbelems;
}

/* returns pointer to elements at index id */
void *aml_vector_get(struct aml_vector *vec, int id)
{
	assert(vec != NULL);
50
51
52
53
54
55
56
	if (id == vec->na || id < 0)
		return NULL;

	size_t idx = (size_t)id;

	if (idx < vec->nbelems)
		return AML_VECTOR_ELT_P(vec, idx);
57
58
59
60
61
	else
		return NULL;
}

/* return index of first element with key */
62
int aml_vector_find(const struct aml_vector *vec, int key)
63
64
{
	assert(vec != NULL);
65
	for (size_t i = 0; i < vec->nbelems; i++) {
66
		int *k = AML_VECTOR_KEY_P(vec, i);
67
68

		if (*k == key)
69
70
71
72
73
74
75
76
77
			return i;
	}
	return vec->na;
}

void *aml_vector_add(struct aml_vector *vec)
{
	assert(vec != NULL);
	int idx = aml_vector_find(vec, vec->na);
78
79

	if (idx == vec->na) {
80
81
		/* exponential growth, good to amortize cost */
		idx = vec->nbelems;
82
		aml_vector_resize(vec, vec->nbelems * 2);
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
	}
	return AML_VECTOR_ELT_P(vec, idx);
}

void aml_vector_remove(struct aml_vector *vec, void *elem)
{
	assert(vec != NULL);
	assert(elem != NULL);
	assert(elem >= vec->ptr && elem < AML_VECTOR_ELT_P(vec, vec->nbelems));

	int *k = AML_VECTOR_ELTKEY_P(vec, elem);
	*k = vec->na;
}

/*******************************************************************************
98
 * Create/Destroy:
99
100
 ******************************************************************************/

101
102
103
104
int aml_vector_create(struct aml_vector **vec, size_t reserve, size_t size,
		      size_t key, int na)
{
	struct aml_vector *ret = NULL;
105
	void *ptr;
106
107
108
109
110
111
112
113
114
115
116

	if (vec == NULL)
		return -AML_EINVAL;

	ret = malloc(sizeof(struct aml_vector));
	if (ret == NULL) {
		*vec = NULL;
		return -AML_ENOMEM;
	}

	ptr = calloc(reserve, size);
117
118
119
	if (ptr == NULL) {
		free(ret);
		*vec = NULL;
120
		return -AML_ENOMEM;
121
	}
122

123
124
125
126
127
128
129
	ret->sz = size;
	ret->off = key;
	ret->na = na;
	ret->nbelems = reserve;
	ret->ptr = ptr;
	for (size_t i = 0; i < ret->nbelems; i++) {
		int *k = AML_VECTOR_KEY_P(ret, i);
130
131
		*k = na;
	}
132
133

	*vec = ret;
134
135
136
	return 0;
}

137
void aml_vector_destroy(struct aml_vector **vec)
138
{
139
140
	struct aml_vector *v;

141
142
143
	if (vec == NULL)
		return;

144
145
	v = *vec;
	if (v == NULL)
146
		return;
147
148
149

	free(v->ptr);
	free(v);
150
	*vec = NULL;
151
}