excit.c 6.78 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"
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
/*--------------------------------------------------------------------*/

Nicolas Denoyelle's avatar
Nicolas Denoyelle committed
85 86 87 88 89 90 91 92 93 94 95 96
#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;\
}
97

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
{
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;
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
}

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