-
Notifications
You must be signed in to change notification settings - Fork 0
/
tds_vec.c
132 lines (119 loc) · 2.65 KB
/
tds_vec.c
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#include <string.h> /* for memmove */
#include "tds_utils.h"
#include "tds_vec.h"
#if HAS_TORCH
#include "THAtomic.h"
#endif
/* note: size_t >= 0 */
struct tds_vec_ {
tds_elem *data;
size_t n; /* number of elements */
size_t allocn; /* number of allocated elements */
int refcount;
};
tds_vec* tds_vec_new(void)
{
tds_vec *vec = tds_malloc(sizeof(tds_vec));
if(!vec)
return NULL;
vec->data = NULL;
vec->allocn = 0;
vec->n = 0;
vec->refcount = 1;
return vec;
}
size_t tds_vec_size(tds_vec *vec)
{
return vec->n;
}
int tds_vec_insert(tds_vec *vec, size_t idx, tds_elem *val)
{
if(tds_vec_resize(vec, vec->n+1))
return 1;
if(vec->n-idx-1 > 0)
memmove(vec->data+idx+1, vec->data+idx, sizeof(tds_elem)*(vec->n-idx-1));
vec->data[idx] = *val;
return 0;
}
int tds_vec_set(tds_vec *vec, size_t idx, tds_elem *val)
{
if(idx >= vec->n) {
if(tds_vec_resize(vec, idx+1))
return 1;
}
tds_elem_free_content(&vec->data[idx]);
vec->data[idx] = *val;
return 0;
}
int tds_vec_get(tds_vec *vec, size_t idx, tds_elem *val)
{
if(idx >= vec->n) {
tds_elem_set_nil(val);
return 0;
}
*val = vec->data[idx];
return 0;
}
int tds_vec_remove(tds_vec *vec, size_t idx)
{
if(idx >= vec->n)
return 0;
tds_elem_free_content(&vec->data[idx]);
if(vec->n-idx-1 > 0)
memmove(vec->data+idx, vec->data+idx+1, sizeof(tds_elem)*(vec->n-idx-1));
vec->n--;
return 0;
}
int tds_vec_resize(tds_vec *vec, size_t size)
{
size_t k;
if(size == vec->n) {
return 0;
} else if(size > vec->n) {
if(size > vec->allocn) {
/* always allocate at least 1.5x more at each time */
size_t allocn = (vec->allocn*1.5 > size ? vec->allocn*1.5 : size);
tds_elem *data = tds_realloc(vec->data, sizeof(tds_elem)*allocn);
if(!data)
return 1;
vec->data = data;
vec->allocn = allocn;
}
for(k = vec->n; k < size; k++)
tds_elem_set_nil(&vec->data[k]);
vec->n = size;
} else {
for(k = size; k < vec->n; k++)
tds_elem_free_content(&vec->data[k]);
vec->n = size;
}
return 0;
}
void tds_vec_sort(tds_vec *vec, int (*compare)(const tds_elem *elem1, const tds_elem *elem2))
{
qsort(vec->data, vec->n, sizeof(tds_elem), (int (*)(const void*, const void*))(compare));
}
void tds_vec_retain(tds_vec *vec)
{
#if HAS_TORCH
THAtomicIncrementRef(&vec->refcount);
#else
vec->refcount++;
#endif
}
void tds_vec_free(tds_vec* vec)
{
size_t k;
#if HAS_TORCH
if(THAtomicDecrementRef(&vec->refcount))
#else
vec->refcount--;
if(vec->refcount == 0)
#endif
{
for(k = 0; k < vec->n; k++)
tds_elem_free_content(&vec->data[k]);
tds_free(vec->data);
tds_free(vec);
}
}