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

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

13
const char *excit_type_name(enum excit_type_e type)
14
{
15
	switch (type) {
Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
16 17 18 19 20 21 22 23
		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);
24 25 26 27 28
	default:
		return NULL;
	}
}

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

#undef CASE

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
int excit_set_dimension(excit_t it, ssize_t dimension)
{
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	it->dimension = dimension;
	return EXCIT_SUCCESS;
}

int excit_get_data(excit_t it, void **data)
{
	if (!it)
		return -EXCIT_EINVAL;
	if (it->type != EXCIT_USER)
		return -EXCIT_ENOTSUP;
	*data = it->data;
	return EXCIT_SUCCESS;
}

int excit_set_func_table(excit_t it, struct excit_func_table_s *func_table)
{
	if (!it)
		return -EXCIT_EINVAL;
	it->func_table = func_table;
	return EXCIT_SUCCESS;
}

int excit_get_func_table(excit_t it, struct excit_func_table_s **func_table)
{
	if (!it)
		return -EXCIT_EINVAL;
	*func_table = it->func_table;
	return EXCIT_SUCCESS;
}

82 83
/*--------------------------------------------------------------------*/

84 85 86 87 88 89 90 91 92 93 94
#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; \
95 96
}

Brice Videau's avatar
Brice Videau committed
97
excit_t excit_alloc(enum excit_type_e type)
98
{
99
	excit_t it = NULL;
100 101

	switch (type) {
Brice Videau's avatar
Brice Videau committed
102
	case EXCIT_RANGE:
103
		ALLOC_EXCIT(range);
104
		break;
Brice Videau's avatar
Brice Videau committed
105
	case EXCIT_CONS:
106
		ALLOC_EXCIT(cons);
107
		break;
Brice Videau's avatar
Brice Videau committed
108
	case EXCIT_REPEAT:
109
		ALLOC_EXCIT(repeat);
110
		break;
Brice Videau's avatar
Brice Videau committed
111
	case EXCIT_HILBERT2D:
112
		ALLOC_EXCIT(hilbert2d);
113
		break;
Brice Videau's avatar
Brice Videau committed
114
	case EXCIT_PRODUCT:
115
		ALLOC_EXCIT(prod);
116
		break;
Brice Videau's avatar
Brice Videau committed
117
	case EXCIT_SLICE:
118
		ALLOC_EXCIT(slice);
119 120 121 122
		break;
	default:
		goto error;
	}
123 124
	it->type = type;
	return it;
125
error:
126
	free(it);
127 128 129
	return NULL;
}

130 131
excit_t excit_alloc_user(struct excit_func_table_s *func_table,
			 size_t data_size)
132 133 134
{
	excit_t it;

135 136 137
	if (!func_table || !data_size)
		return NULL;
	it = malloc(sizeof(struct excit_s) + data_size);
138 139
	if (!it)
		return NULL;
140 141 142 143 144
	it->data = (void *)((char *)it + sizeof(struct excit_s));
	if (!func_table->alloc)
		goto error;
	it->func_table = func_table;
	it->dimension = 0;
145
	it->type = EXCIT_USER;
146 147
	if (func_table->alloc(it))
		goto error;
148 149 150 151 152 153
	return it;
error:
	free(it);
	return NULL;
}

154
excit_t excit_dup(excit_t it)
155
{
Brice Videau's avatar
Brice Videau committed
156
	excit_t result = NULL;
157

158
	if (!it || !it->data || !it->func_table || !it->func_table->copy)
159
		return NULL;
160
	result = excit_alloc(it->type);
161 162
	if (!result)
		return NULL;
163
	result->dimension = it->dimension;
164
	if (it->func_table->copy(result, it))
165 166 167
		goto error;
	return result;
error:
Brice Videau's avatar
Brice Videau committed
168
	excit_free(result);
169 170 171
	return NULL;
}

172
void excit_free(excit_t it)
173
{
174
	if (!it)
175
		return;
176
	if (!it->func_table)
177
		goto error;
178 179
	if (it->func_table->free)
		it->func_table->free(it);
180
error:
181
	free(it);
182 183
}

184
int excit_dimension(excit_t it, ssize_t *dimension)
185
{
186
	if (!it || !dimension)
Brice Videau's avatar
Brice Videau committed
187
		return -EXCIT_EINVAL;
188
	*dimension = it->dimension;
Brice Videau's avatar
Brice Videau committed
189
	return EXCIT_SUCCESS;
190 191
}

192
int excit_type(excit_t it, enum excit_type_e *type)
193
{
194
	if (!it || !type)
Brice Videau's avatar
Brice Videau committed
195
		return -EXCIT_EINVAL;
196
	*type = it->type;
Brice Videau's avatar
Brice Videau committed
197
	return EXCIT_SUCCESS;
198 199
}

200
int excit_next(excit_t it, ssize_t *indexes)
201
{
202
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
203
		return -EXCIT_EINVAL;
204
	if (!it->func_table->next)
Brice Videau's avatar
Brice Videau committed
205
		return -EXCIT_ENOTSUP;
206
	return it->func_table->next(it, indexes);
207 208
}

209
int excit_peek(const excit_t it, ssize_t *indexes)
210
{
211
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
212
		return -EXCIT_EINVAL;
213
	if (!it->func_table->peek)
Brice Videau's avatar
Brice Videau committed
214
		return -EXCIT_ENOTSUP;
215
	return it->func_table->peek(it, indexes);
216 217
}

218
int excit_size(const excit_t it, ssize_t *size)
219
{
220
	if (!it || !it->func_table || !size)
Brice Videau's avatar
Brice Videau committed
221
		return -EXCIT_EINVAL;
222
	if (!it->func_table->size)
Brice Videau's avatar
Brice Videau committed
223
		return -EXCIT_ENOTSUP;
224
	return it->func_table->size(it, size);
225 226
}

227
int excit_rewind(excit_t it)
228
{
229
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
230
		return -EXCIT_EINVAL;
231
	if (!it->func_table->rewind)
Brice Videau's avatar
Brice Videau committed
232
		return -EXCIT_ENOTSUP;
233
	return it->func_table->rewind(it);
234 235
}

236
int excit_split(const excit_t it, ssize_t n, excit_t *results)
237
{
238
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
239
		return -EXCIT_EINVAL;
240
	if (n <= 0)
Brice Videau's avatar
Brice Videau committed
241
		return -EXCIT_EDOM;
242
	if (!it->func_table->split)
Brice Videau's avatar
Brice Videau committed
243
		return -EXCIT_ENOTSUP;
244
	return it->func_table->split(it, n, results);
245 246
}

247
int excit_nth(const excit_t it, ssize_t n, ssize_t *indexes)
248
{
249
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
250
		return -EXCIT_EINVAL;
251
	if (!it->func_table->nth)
Brice Videau's avatar
Brice Videau committed
252
		return -EXCIT_ENOTSUP;
253
	return it->func_table->nth(it, n, indexes);
254 255
}

256
int excit_rank(const excit_t it, const ssize_t *indexes, ssize_t *n)
257
{
258
	if (!it || !it->func_table || !indexes)
Brice Videau's avatar
Brice Videau committed
259
		return -EXCIT_EINVAL;
260
	if (!it->func_table->rank)
Brice Videau's avatar
Brice Videau committed
261
		return -EXCIT_ENOTSUP;
262
	return it->func_table->rank(it, indexes, n);
263 264
}

265
int excit_pos(const excit_t it, ssize_t *n)
266
{
267
	if (!it || !it->func_table)
Brice Videau's avatar
Brice Videau committed
268
		return -EXCIT_EINVAL;
269
	if (!it->func_table->pos)
Brice Videau's avatar
Brice Videau committed
270
		return -EXCIT_ENOTSUP;
271
	return it->func_table->pos(it, n);
272 273
}

274
int excit_cyclic_next(excit_t it, ssize_t *indexes, int *looped)
275 276 277
{
	int err;

278
	if (!it)
Brice Videau's avatar
Brice Videau committed
279
		return -EXCIT_EINVAL;
280
	*looped = 0;
281
	err = excit_next(it, indexes);
282
	switch (err) {
Brice Videau's avatar
Brice Videau committed
283
	case EXCIT_SUCCESS:
284
		break;
Brice Videau's avatar
Brice Videau committed
285
	case EXCIT_STOPIT:
286
		err = excit_rewind(it);
287 288 289
		if (err)
			return err;
		*looped = 1;
290
		err = excit_next(it, indexes);
291 292 293 294 295 296
		if (err)
			return err;
		break;
	default:
		return err;
	}
297 298
	if (excit_peek(it, NULL) == EXCIT_STOPIT) {
		err = excit_rewind(it);
299 300 301 302
		if (err)
			return err;
		*looped = 1;
	}
Brice Videau's avatar
Brice Videau committed
303
	return EXCIT_SUCCESS;
304 305
}

306
int excit_skip(excit_t it)
307
{
308
	return excit_next(it, NULL);
309
}