-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathntuple.c
217 lines (159 loc) · 4.17 KB
/
ntuple.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "trurl_internal.h"
#include "nmalloc.h"
#include "tfn_types.h"
#include "ntuple.h"
#include <trurl/nmalloc.h>
const char *n_errmsg_tuple_nth_oob = "n_tuple_nth: index(%d) out of bounds(%d)\n";
tn_tuple *n_tuple_new(tn_alloc *na, int size, void **data)
{
tn_tuple *tu;
n_assert(size < UINT16_MAX);
if (na)
tu = na->na_malloc(na, sizeof(*tu) + (size * sizeof(void*)));
else
tu = n_malloc(sizeof(*tu) + (size * sizeof(void*)));
tu->_refcnt = 0;
tu->size = size;
if (data)
memcpy(tu->data, data, size * sizeof(void*));
else if (size)
memset(tu->data, 0, size * sizeof(void*));
return tu;
}
#include <trurl/narray.h>
tn_tuple *n_tuple_new_fromarray(tn_alloc *na, tn_array *arr)
{
tn_tuple *tu = n_tuple_new(na, n_array_size(arr), NULL);
register int i;
i = 0;
while (n_array_size(arr) > 0)
tu->data[i++] = n_array_shift(arr);
return tu;
}
void n_tuple_free(tn_alloc *na, tn_tuple *tu)
{
if (tu->_refcnt > 0) {
tu->_refcnt--;
return;
}
tu->size = 0;
if (na)
na->na_free(na, tu);
else
n_free(tu);
}
#undef n_tuple_size
int n_tuple_size(const tn_tuple *tu)
{
return tu->size;
}
#undef n_tuple_nth
void *n_tuple_nth(const tn_tuple *tu, register int i)
{
if ((size_t) i >= tu->size || i < 0)
n_die(n_errmsg_tuple_nth_oob, i, tu->size);
return tu->data[i];
}
extern
void trurl_isort_voidp_arr(void **arr, size_t arr_size, t_fn_cmp cmpf);
extern
void trurl_qsort_voidp_arr(void **arr, size_t arr_size, t_fn_cmp cmpf);
#define SORT_SORT 0
#define SORT_QSORT 1
#define SORT_ISORT 2
static inline tn_tuple *n_tuple_sort_internal(tn_tuple *tu, t_fn_cmp cmpf, int alg)
{
switch (alg) {
case SORT_SORT:
if (tu->size > 10)
trurl_qsort_voidp_arr(&tu->data[0], tu->size, cmpf);
else
trurl_isort_voidp_arr(&tu->data[0], tu->size, cmpf);
break;
case SORT_QSORT:
trurl_qsort_voidp_arr(&tu->data[0], tu->size, cmpf);
break;
case SORT_ISORT:
trurl_isort_voidp_arr(&tu->data[0], tu->size, cmpf);
break;
}
return tu;
}
tn_tuple *n_tuple_sort_ex(tn_tuple *tu, t_fn_cmp cmpf)
{
return n_tuple_sort_internal(tu, cmpf, SORT_SORT);
}
tn_tuple *n_tuple_qsort_ex(tn_tuple *tu, t_fn_cmp cmpf)
{
return n_tuple_sort_internal(tu, cmpf, SORT_QSORT);
}
tn_tuple *n_tuple_isort_ex(tn_tuple *tu, t_fn_cmp cmpf)
{
return n_tuple_sort_internal(tu, cmpf, SORT_ISORT);
}
static __inline__
int bsearch_voidp_tu(void *const *arr, size_t arr_size, const void *data,
t_fn_cmp cmpf)
{
register size_t l, r, i;
int cmp_res;
l = 0;
r = arr_size;
while (l < r) {
i = (l + r) / 2;
if ((cmp_res = cmpf(arr[i], data)) == 0) {
return i;
} else if (cmp_res > 0) {
r = i;
} else if (cmp_res < 0) {
l = i + 1;
}
}
return -1;
}
int n_tuple_bsearch_idx_ex(const tn_tuple *tu, const void *data,
t_fn_cmp cmpf)
{
int idx;
void **base;
if (tu->size == 0)
return -1;
base = (void**)tu->data;
if (tu->size > 1) {
idx = bsearch_voidp_tu(base, tu->size, data, cmpf);
if (idx > 0) {
while (idx) {
if (cmpf(base[idx - 1], data) != 0)
break;
idx--;
}
}
} else {
idx = -1;
if (cmpf(base[0], data) == 0)
idx = 0;
}
return idx;
}
void *n_tuple_bsearch_ex(const tn_tuple *tu, const void *data, t_fn_cmp cmpf)
{
int idx;
void **base;
if (tu->size == 0)
return NULL;
base = (void**)tu->data;
if (tu->size > 1) {
idx = bsearch_voidp_tu(base, tu->size, data, cmpf);
} else {
idx = -1;
if (cmpf(base[0], data) == 0)
idx = 0;
}
return idx < 0 ? NULL : base[idx];
}