excit.c 6.79 KB
Newer Older
1
#include <stdlib.h>
2
#include "excit.h"
3
#include "dev/excit.h"
4
5
6
#include "slice.h"
#include "prod.h"
#include "cons.h"
7
#include "repeat.h"
8
#include "hilbert2d.h"
9
#include "range.h"
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
10
#include "tleaf.h"
Brice Videau's avatar
Brice Videau committed
11

Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
12
#define CASE(val) case val: return #val; break
13

14
const char *excit_type_name(enum excit_type_e type)
15
{
16
	switch (type) {
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
17
18
19
20
21
22
23
24
		CASE(EXCIT_RANGE);
		CASE(EXCIT_CONS);
		CASE(EXCIT_REPEAT);
		CASE(EXCIT_HILBERT2D);
		CASE(EXCIT_PRODUCT);
		CASE(EXCIT_SLICE);
		CASE(EXCIT_USER);
		CASE(EXCIT_TYPE_MAX);
25
26
27
28
29
	default:
		return NULL;
	}
}

30
const char *excit_error_name(enum excit_error_e err)
31
{
32
	switch (err) {
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
33
34
35
36
37
38
39
		CASE(EXCIT_SUCCESS);
		CASE(EXCIT_STOPIT);
		CASE(EXCIT_ENOMEM);
		CASE(EXCIT_EINVAL);
		CASE(EXCIT_EDOM);
		CASE(EXCIT_ENOTSUP);
		CASE(EXCIT_ERROR_MAX);
40
41
42
43
44
45
46
	default:
		return NULL;
	}
}

#undef CASE

47
48
int excit_set_dimension(excit_t it, ssize_t dimension)
{
49
50
51
52
53
54
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	it->dimension = dimension;
	return EXCIT_SUCCESS;
55
56
}

57
int excit_get_data(excit_t it, void **data)
58
{
59
60
61
62
63
64
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	*data = it->data;
	return EXCIT_SUCCESS;
65
66
}

67
int excit_set_func_table(excit_t it, struct excit_func_table_s *func_table)
68
{
69
70
71
72
	if (!it)
		return -EXCIT_EINVAL;
	it->func_table = func_table;
	return EXCIT_SUCCESS;
73
74
}

75
int excit_get_func_table(excit_t it, struct excit_func_table_s **func_table)
76
{
77
78
79
80
	if (!it)
		return -EXCIT_EINVAL;
	*func_table = it->func_table;
	return EXCIT_SUCCESS;
81
82
}

83
84
/*--------------------------------------------------------------------*/

Brice Videau's avatar
Brice Videau committed
85
86
87
88
89
90
91
92
93
94
95
#define ALLOC_EXCIT(op) { \
	it = malloc(sizeof(struct excit_s) + sizeof(struct op## _it_s)); \
	if (!it) \
		return NULL; \
	it->data = (void *)((char *)it + sizeof(struct excit_s)); \
	if (!excit_ ##op## _func_table.alloc) \
		goto error; \
	it->func_table = &excit_ ##op## _func_table; \
	it->dimension = 0; \
	if (excit_ ##op## _func_table.alloc(it)) \
		goto error; \
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
96
}
97

Brice Videau's avatar
Brice Videau committed
98
excit_t excit_alloc(enum excit_type_e type)
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
	excit_t it = NULL;

	switch (type) {
	case EXCIT_RANGE:
		ALLOC_EXCIT(range);
		break;
	case EXCIT_CONS:
		ALLOC_EXCIT(cons);
		break;
	case EXCIT_REPEAT:
		ALLOC_EXCIT(repeat);
		break;
	case EXCIT_HILBERT2D:
		ALLOC_EXCIT(hilbert2d);
		break;
	case EXCIT_PRODUCT:
		ALLOC_EXCIT(prod);
		break;
	case EXCIT_SLICE:
		ALLOC_EXCIT(slice);
		break;
	case EXCIT_TLEAF:
		ALLOC_EXCIT(tleaf);
		break;
	default:
		goto error;
	}
	it->type = type;
	return it;
129
error:
130
131
	free(it);
	return NULL;
132
133
}

134
135
excit_t excit_alloc_user(struct excit_func_table_s *func_table,
			 size_t data_size)
136
{
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
	excit_t it;

	if (!func_table || !data_size)
		return NULL;
	it = malloc(sizeof(struct excit_s) + data_size);
	if (!it)
		return NULL;
	it->data = (void *)((char *)it + sizeof(struct excit_s));
	if (!func_table->alloc)
		goto error;
	it->func_table = func_table;
	it->dimension = 0;
	it->type = EXCIT_USER;
	if (func_table->alloc(it))
		goto error;
	return it;
153
error:
154
155
	free(it);
	return NULL;
156
157
}

158
excit_t excit_dup(excit_t it)
159
{
Brice Videau's avatar
Brice Videau committed
160
	excit_t result = NULL;
161

162
	if (!it || !it->data || !it->func_table || !it->func_table->copy)
163
		return NULL;
164
	result = excit_alloc(it->type);
165
166
	if (!result)
		return NULL;
167
	result->dimension = it->dimension;
168
	if (it->func_table->copy(result, it))
169
170
171
		goto error;
	return result;
error:
172
173
	excit_free(result);
	return NULL;
174
175
}

176
void excit_free(excit_t it)
177
{
178
179
180
181
182
183
	if (!it)
		return;
	if (!it->func_table)
		goto error;
	if (it->func_table->free)
		it->func_table->free(it);
184
error:
185
	free(it);
186
187
}

188
int excit_dimension(excit_t it, ssize_t *dimension)
189
{
190
191
192
193
	if (!it || !dimension)
		return -EXCIT_EINVAL;
	*dimension = it->dimension;
	return EXCIT_SUCCESS;
194
195
}

196
int excit_type(excit_t it, enum excit_type_e *type)
197
{
198
199
200
201
202
203
	if (!it || !type)
		return -EXCIT_EINVAL;
	*type = it->type;
	return EXCIT_SUCCESS;
}

204
int excit_next(excit_t it, ssize_t *indexes)
205
{
206
207
208
209
210
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->next)
		return -EXCIT_ENOTSUP;
	return it->func_table->next(it, indexes);
211
212
}

213
int excit_peek(const excit_t it, ssize_t *indexes)
214
{
215
216
217
218
219
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->peek)
		return -EXCIT_ENOTSUP;
	return it->func_table->peek(it, indexes);
220
221
}

222
int excit_size(const excit_t it, ssize_t *size)
223
{
224
225
226
227
228
	if (!it || !it->func_table || !size)
		return -EXCIT_EINVAL;
	if (!it->func_table->size)
		return -EXCIT_ENOTSUP;
	return it->func_table->size(it, size);
229
230
}

231
int excit_rewind(excit_t it)
232
{
233
234
235
236
237
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->rewind)
		return -EXCIT_ENOTSUP;
	return it->func_table->rewind(it);
238
239
}

240
int excit_split(const excit_t it, ssize_t n, excit_t *results)
241
{
242
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
243
		return -EXCIT_EINVAL;
244
	if (n <= 0)
Brice Videau's avatar
Brice Videau committed
245
		return -EXCIT_EDOM;
Brice Videau's avatar
Brice Videau committed
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
	if (!it->func_table->split) {
		ssize_t size;
		int err = excit_size(it, &size);

		if (err)
			return err;
		if (size < n)
			return -EXCIT_EDOM;
		if (!results)
			return EXCIT_SUCCESS;
		excit_t range = excit_alloc(EXCIT_RANGE);

		if (!range)
			return -EXCIT_ENOMEM;
		err = excit_range_init(range, 0, size - 1, 1);
		if (err)
			goto error1;
		err = excit_split(range, n, results);
		if (err)
			goto error1;
		for (int i = 0; i < n; i++) {
			excit_t tmp, tmp2;

			tmp = excit_dup(it);
			if (!tmp)
				goto error2;
			tmp2 = results[i];
			results[i] = excit_alloc(EXCIT_SLICE);
			if (!results[i]) {
				excit_free(tmp2);
				goto error2;
			}
			err = excit_slice_init(results[i], tmp, tmp2);
			if (err) {
				excit_free(tmp2);
				goto error2;
			}
		}
		excit_free(range);
		return EXCIT_SUCCESS;
error2:
		for (int i = 0; i < n; i++)
			excit_free(results[i]);
error1:
		excit_free(range);
		return err;
	} else
		return it->func_table->split(it, n, results);
294
295
}

296
int excit_nth(const excit_t it, ssize_t n, ssize_t *indexes)
297
{
298
299
300
301
302
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->nth)
		return -EXCIT_ENOTSUP;
	return it->func_table->nth(it, n, indexes);
303
304
}

Brice Videau's avatar
Brice Videau committed
305
int excit_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
306
{
307
308
309
310
311
	if (!it || !it->func_table || !indexes)
		return -EXCIT_EINVAL;
	if (!it->func_table->rank)
		return -EXCIT_ENOTSUP;
	return it->func_table->rank(it, indexes, n);
312
313
}

314
int excit_pos(const excit_t it, ssize_t *n)
315
{
316
317
318
319
320
	if (!it || !it->func_table)
		return -EXCIT_EINVAL;
	if (!it->func_table->pos)
		return -EXCIT_ENOTSUP;
	return it->func_table->pos(it, n);
321
322
}

323
int excit_cyclic_next(excit_t it, ssize_t *indexes, int *looped)
324
{
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
	int err;

	if (!it)
		return -EXCIT_EINVAL;
	*looped = 0;
	err = excit_next(it, indexes);
	switch (err) {
	case EXCIT_SUCCESS:
		break;
	case EXCIT_STOPIT:
		err = excit_rewind(it);
		if (err)
			return err;
		*looped = 1;
		err = excit_next(it, indexes);
		if (err)
			return err;
		break;
	default:
		return err;
	}
	if (excit_peek(it, NULL) == EXCIT_STOPIT) {
		err = excit_rewind(it);
		if (err)
			return err;
		*looped = 1;
	}
	return EXCIT_SUCCESS;
353
354
}

355
int excit_skip(excit_t it)
356
{
357
	return excit_next(it, NULL);
358
}
359