excit.c 35.5 KB
Newer Older
1
#include <stdlib.h>
2 3
#include <excit.h>

4 5
/*--------------------------------------------------------------------*/

6
struct slice_it_s {
7 8
	excit_t src;
	excit_t indexer;
9 10
};

11
static int slice_it_alloc(excit_t data)
12
{
13
	data->data = malloc(sizeof(struct slice_it_s));
14
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
15
		return -EXCIT_ENOMEM;
16
	struct slice_it_s *it = (struct slice_it_s *) data->data;
17

18 19
	it->src = NULL;
	it->indexer = NULL;
Brice Videau's avatar
Brice Videau committed
20
	return EXCIT_SUCCESS;
21 22
}

23
static void slice_it_free(excit_t data)
24
{
25
	struct slice_it_s *it = (struct slice_it_s *) data->data;
26

27 28
	excit_free(it->src);
	excit_free(it->indexer);
29 30 31
	free(data->data);
}

32
static int slice_it_copy(excit_t dst, const excit_t src)
33
{
34 35
	const struct slice_it_s *it = (const struct slice_it_s *) src->data;
	struct slice_it_s *result = (struct slice_it_s *) dst->data;
36

37
	result->src = excit_dup(it->src);
38
	if (!result->src)
Brice Videau's avatar
Brice Videau committed
39
		return -EXCIT_ENOMEM;
40
	result->indexer = excit_dup(it->indexer);
41
	if (!result->indexer) {
42
		excit_free(it->src);
Brice Videau's avatar
Brice Videau committed
43
		return -EXCIT_ENOMEM;
44
	}
Brice Videau's avatar
Brice Videau committed
45
	return EXCIT_SUCCESS;
46 47
}

48
static int slice_it_next(excit_t data, ssize_t *indexes)
49
{
50 51 52
	struct slice_it_s *it = (struct slice_it_s *) data->data;
	ssize_t n;
	int err = excit_next(it->indexer, &n);
53 54 55

	if (err)
		return err;
56
	return excit_nth(it->src, n, indexes);
57 58
}

59
static int slice_it_peek(const excit_t data, ssize_t *indexes)
60
{
61 62 63
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t n;
	int err = excit_peek(it->indexer, &n);
64 65 66

	if (err)
		return err;
67
	return excit_nth(it->src, n, indexes);
68 69
}

70
static int slice_it_size(const excit_t data, ssize_t *size)
71
{
72
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
73

74
	return excit_size(it->indexer, size);
75 76
}

77
static int slice_it_rewind(excit_t data)
78
{
79
	struct slice_it_s *it = (struct slice_it_s *) data->data;
80

81
	return excit_rewind(it->indexer);
82 83
}

84
static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
85
{
86 87 88
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t p;
	int err = excit_nth(it->indexer, n, &p);
89 90 91

	if (err)
		return err;
92
	return excit_nth(it->src, p, indexes);
93 94
}

95
static int slice_it_n(const excit_t data, const ssize_t *indexes, ssize_t *n)
96
{
97 98 99
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t inner_n;
	int err = excit_n(it->src, indexes, &inner_n);
100 101 102

	if (err)
		return err;
103
	return excit_n(it->indexer, &inner_n, n);
104 105
}

106
static int slice_it_pos(const excit_t data, ssize_t *n)
107
{
108
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
109

110
	return excit_pos(it->indexer, n);
111 112
}

113
static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
114
{
115 116
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	int err = excit_split(it->indexer, n, results);
117 118 119 120

	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
121
		return EXCIT_SUCCESS;
122
	for (int i = 0; i < n; i++) {
123 124
		excit_t tmp;
		excit_t tmp2;
125 126

		tmp = results[i];
127
		results[i] = excit_alloc(EXCIT_SLICE);
128
		if (!results[i]) {
129
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
130
			err = -EXCIT_ENOMEM;
131 132
			goto error;
		}
133
		tmp2 = excit_dup(it->src);
134
		if (!tmp2) {
135
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
136
			err = -EXCIT_ENOMEM;
137 138
			goto error;
		}
139
		err = excit_slice_init(results[i], tmp, tmp2);
140
		if (err) {
141 142
			excit_free(tmp);
			excit_free(tmp2);
143 144 145
			goto error;
		}
	}
Brice Videau's avatar
Brice Videau committed
146
	return EXCIT_SUCCESS;
147 148
error:
	for (int i = 0; i < n; i++)
149
		excit_free(results[i]);
150 151 152
	return err;
}

153
static const struct excit_func_table_s excit_slice_func_table = {
154 155 156 157 158 159 160 161 162 163 164
	slice_it_alloc,
	slice_it_free,
	slice_it_copy,
	slice_it_next,
	slice_it_peek,
	slice_it_size,
	slice_it_rewind,
	slice_it_split,
	slice_it_nth,
	slice_it_n,
	slice_it_pos
165 166
};

167
int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
168
{
169 170
	if (!it || it->type != EXCIT_SLICE || !src || !indexer
		|| indexer->dimension != 1)
Brice Videau's avatar
Brice Videau committed
171
		return -EXCIT_EINVAL;
172 173 174
	struct slice_it_s *slice_it = (struct slice_it_s *) it->data;
	ssize_t size_src;
	ssize_t size_indexer;
175
	int err = excit_size(src, &size_src);
176 177 178

	if (err)
		return err;
179
	err = excit_size(indexer, &size_indexer);
180 181 182
	if (err)
		return err;
	if (size_indexer > size_src)
Brice Videau's avatar
Brice Videau committed
183
		return -EXCIT_EDOM;
184 185 186
	slice_it->src = src;
	slice_it->indexer = indexer;
	it->dimension = src->dimension;
Brice Videau's avatar
Brice Videau committed
187
	return EXCIT_SUCCESS;
188 189 190 191
}

/*--------------------------------------------------------------------*/

192 193 194
struct prod_it_s {
	ssize_t count;
	excit_t *its;
195 196
};

197
static int prod_it_alloc(excit_t data)
198
{
199
	data->data = malloc(sizeof(struct prod_it_s));
200
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
201
		return -EXCIT_ENOMEM;
202
	struct prod_it_s *it = (struct prod_it_s *) data->data;
203

204 205
	it->count = 0;
	it->its = NULL;
Brice Videau's avatar
Brice Videau committed
206
	return EXCIT_SUCCESS;
207 208
}

209
static void prod_it_free(excit_t data)
210
{
211 212 213 214 215
	struct prod_it_s *it = (struct prod_it_s *) data->data;
	if (it->its) {
		for (ssize_t i = 0; i < it->count; i++)
			excit_free(it->its[i]);
		free(it->its);
216 217 218 219
	}
	free(data->data);
}

220
static int prod_it_copy(excit_t dst, const excit_t src)
221
{
222 223
	const struct prod_it_s *it = (const struct prod_it_s *)src->data;
	struct prod_it_s *result = (struct prod_it_s *) dst->data;
224

225 226
	result->its = (excit_t *) malloc(it->count * sizeof(excit_t));
	if (!result->its)
Brice Videau's avatar
Brice Videau committed
227
		return -EXCIT_ENOMEM;
228
	ssize_t i;
229

230 231 232
	for (i = 0; i < it->count; i++) {
		result->its[i] = excit_dup(it->its[i]);
		if (!result->its[i]) {
233 234 235 236
			i--;
			goto error;
		}
	}
237
	result->count = it->count;
Brice Videau's avatar
Brice Videau committed
238
	return EXCIT_SUCCESS;
239 240
error:
	while (i >= 0) {
241
		free(result->its[i]);
242 243
		i--;
	}
244
	free(result->its);
Brice Videau's avatar
Brice Videau committed
245
	return -EXCIT_ENOMEM;
246 247
}

248
static int prod_it_rewind(excit_t data)
249
{
250
	struct prod_it_s *it = (struct prod_it_s *) data->data;
251

252 253
	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_rewind(it->its[i]);
254 255 256 257

		if (err)
			return err;
	}
Brice Videau's avatar
Brice Videau committed
258
	return EXCIT_SUCCESS;
259 260
}

261
static int prod_it_size(const excit_t data, ssize_t *size)
262
{
263 264
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
	ssize_t tmp_size = 0;
265 266

	if (!size)
Brice Videau's avatar
Brice Videau committed
267
		return -EXCIT_EINVAL;
268
	if (it->count == 0)
269 270 271
		*size = 0;
	else {
		*size = 1;
272 273
		for (ssize_t i = 0; i < it->count; i++) {
			int err = excit_size(it->its[i], &tmp_size);
274 275 276 277 278 279 280 281

			if (err) {
				*size = 0;
				return err;
			}
			*size *= tmp_size;
		}
	}
Brice Videau's avatar
Brice Videau committed
282
	return EXCIT_SUCCESS;
283 284
}

285
static int prod_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
286
{
287 288
	ssize_t size;
	int err = prod_it_size(data, &size);
289 290 291 292

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
293
		return -EXCIT_EDOM;
294
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
295 296

	if (indexes) {
297 298
		ssize_t subsize = 0;
		ssize_t offset = data->dimension;
299

300 301 302
		for (ssize_t i = it->count - 1; i >= 0; i--) {
			offset -= it->its[i]->dimension;
			err = excit_size(it->its[i], &subsize);
303 304
			if (err)
				return err;
305 306
			err = excit_nth(it->its[i], n % subsize,
					indexes + offset);
307 308 309 310 311
			if (err)
				return err;
			n /= subsize;
		}
	}
Brice Videau's avatar
Brice Videau committed
312
	return EXCIT_SUCCESS;
313 314
}

315
static int prod_it_n(const excit_t data, const ssize_t *indexes, ssize_t *n)
316
{
317
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
318

319
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
320
		return -EXCIT_EINVAL;
321 322 323 324 325 326 327
	ssize_t offset = 0;
	ssize_t product = 0;
	ssize_t inner_n;
	ssize_t subsize;

	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_n(it->its[i], indexes + offset, &inner_n);
328 329
		if (err)
			return err;
330
		err = excit_size(it->its[i], &subsize);
331 332 333 334
		if (err)
			return err;
		product *= subsize;
		product += inner_n;
335
		offset += it->its[i]->dimension;
336 337 338
	}
	if (n)
		*n = product;
Brice Videau's avatar
Brice Videau committed
339
	return EXCIT_SUCCESS;
340 341
}

342
static int prod_it_pos(const excit_t data, ssize_t *n)
343
{
344
	const struct prod_it_s *it = (const struct prod_it_s *) data->data;
345

346
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
347
		return -EXCIT_EINVAL;
348 349 350
	ssize_t product = 0;
	ssize_t inner_n;
	ssize_t subsize;
351

352 353
	for (ssize_t i = 0; i < it->count; i++) {
		int err = excit_pos(it->its[i], &inner_n);
354 355 356

		if (err)
			return err;
357
		err = excit_size(it->its[i], &subsize);
358 359 360 361 362 363 364
		if (err)
			return err;
		product *= subsize;
		product += inner_n;
	}
	if (n)
		*n = product;
Brice Videau's avatar
Brice Videau committed
365
	return EXCIT_SUCCESS;
366 367
}

368 369
static inline int prod_it_peeknext_helper(excit_t data, ssize_t *indexes,
					  int next)
370
{
371
	struct prod_it_s *it = (struct prod_it_s *) data->data;
372 373
	int err;
	int looped;
374 375 376
	ssize_t i;
	ssize_t *next_indexes;
	ssize_t offset = data->dimension;
377

378
	if (it->count == 0)
Brice Videau's avatar
Brice Videau committed
379
		return -EXCIT_EINVAL;
380
	looped = next;
381
	for (i = it->count - 1; i > 0; i--) {
382
		if (indexes) {
383
			offset -= it->its[i]->dimension;
384 385 386 387
			next_indexes = indexes + offset;
		} else
			next_indexes = NULL;
		if (looped)
388 389
			err = excit_cyclic_next(it->its[i], next_indexes,
						&looped);
390
		else
391
			err = excit_peek(it->its[i], next_indexes);
392 393 394 395
		if (err)
			return err;
	}
	if (indexes) {
396
		offset -= it->its[i]->dimension;
397 398 399 400
		next_indexes = indexes + offset;
	} else
		next_indexes = NULL;
	if (looped)
401
		err = excit_next(it->its[0], next_indexes);
402
	else
403
		err = excit_peek(it->its[0], next_indexes);
404 405
	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
406
	return EXCIT_SUCCESS;
407 408
}

409
static int prod_it_peek(const excit_t data, ssize_t *indexes)
410
{
411
	return prod_it_peeknext_helper(data, indexes, 0);
412 413
}

414
static int prod_it_next(excit_t data, ssize_t *indexes)
415
{
416
	return prod_it_peeknext_helper(data, indexes, 1);
417 418
}

419
static int prod_it_split(const excit_t data, ssize_t n, excit_t *results)
420
{
421 422
	ssize_t size;
	int err = prod_it_size(data, &size);
423 424 425 426

	if (err)
		return err;
	if (size < n)
Brice Videau's avatar
Brice Videau committed
427
		return -EXCIT_EDOM;
428
	if (!results)
Brice Videau's avatar
Brice Videau committed
429
		return EXCIT_SUCCESS;
430
	excit_t range = excit_alloc(EXCIT_RANGE);
431 432

	if (!range)
Brice Videau's avatar
Brice Videau committed
433
		return -EXCIT_ENOMEM;
434
	err = excit_range_init(range, 0, size - 1, 1);
435 436
	if (err)
		goto error1;
437
	err = excit_split(range, n, results);
438 439 440
	if (err)
		goto error1;
	for (int i = 0; i < n; i++) {
441
		excit_t tmp, tmp2;
442

443
		tmp = excit_dup(data);
444 445 446
		if (!tmp)
			goto error2;
		tmp2 = results[i];
447
		results[i] = excit_alloc(EXCIT_SLICE);
448
		if (!results[i]) {
449
			excit_free(tmp2);
450 451
			goto error2;
		}
452
		err = excit_slice_init(results[i], tmp, tmp2);
453
		if (err) {
454
			excit_free(tmp2);
455 456 457
			goto error2;
		}
	}
458
	excit_free(range);
Brice Videau's avatar
Brice Videau committed
459
	return EXCIT_SUCCESS;
460 461
error2:
	for (int i = 0; i < n; i++)
462
		excit_free(results[i]);
463
error1:
464
	excit_free(range);
465 466 467
	return err;
}

468
int excit_product_count(const excit_t it, ssize_t *count)
469
{
470
	if (!it || it->type != EXCIT_PRODUCT || !count)
Brice Videau's avatar
Brice Videau committed
471
		return -EXCIT_EINVAL;
472
	*count = ((struct prod_it_s *) it->data)->count;
Brice Videau's avatar
Brice Videau committed
473
	return EXCIT_SUCCESS;
474 475
}

476 477
int excit_product_split_dim(const excit_t it, ssize_t dim, ssize_t n,
			    excit_t *results)
478
{
479
	if (!it || it->type != EXCIT_PRODUCT)
Brice Videau's avatar
Brice Videau committed
480
		return -EXCIT_EINVAL;
481
	if (n <= 0)
Brice Videau's avatar
Brice Videau committed
482
		return -EXCIT_EDOM;
483 484
	ssize_t count;
	int err = excit_product_count(it, &count);
485 486 487 488

	if (err)
		return err;
	if (dim >= count)
Brice Videau's avatar
Brice Videau committed
489
		return -EXCIT_EDOM;
490
	struct prod_it_s *prod_it = (struct prod_it_s *) it->data;
491

492
	err = excit_split(prod_it->its[dim], n, results);
493 494 495
	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
496
		return EXCIT_SUCCESS;
497
	for (int i = 0; i < n; i++) {
498
		excit_t tmp = results[i];
499

500
		results[i] = excit_dup(it);
501
		if (!tmp) {
502
			excit_free(tmp);
Brice Videau's avatar
Brice Videau committed
503
			err = -EXCIT_ENOMEM;
504 505
			goto error;
		}
506 507 508 509
		struct prod_it_s *new_prod_it =
		    (struct prod_it_s *) results[i]->data;
		excit_free(new_prod_it->its[dim]);
		new_prod_it->its[dim] = tmp;
510
	}
Brice Videau's avatar
Brice Videau committed
511
	return EXCIT_SUCCESS;
512 513
error:
	for (int i = 0; i < n; i++)
514
		excit_free(results[i]);
515 516 517
	return err;
}

518
int excit_product_add_copy(excit_t it, excit_t added_it)
519 520
{
	int err = 0;
521
	excit_t copy = excit_dup(added_it);
522 523

	if (!copy)
Brice Videau's avatar
Brice Videau committed
524
		return -EXCIT_EINVAL;
525
	err = excit_product_add(it, copy);
526
	if (err) {
527
		excit_free(added_it);
528 529
		return err;
	}
Brice Videau's avatar
Brice Videau committed
530
	return EXCIT_SUCCESS;
531 532
}

533
int excit_product_add(excit_t it, excit_t added_it)
534
{
535 536
	if (!it || it->type != EXCIT_PRODUCT || !it->data
	    || !added_it)
Brice Videau's avatar
Brice Videau committed
537
		return -EXCIT_EINVAL;
538

539 540
	struct prod_it_s *prod_it = (struct prod_it_s *) it->data;
	ssize_t mew_count = prod_it->count + 1;
541

542
	excit_t *new_its =
543
	    (excit_t *) realloc(prod_it->its, mew_count * sizeof(excit_t));
544
	if (!new_its)
Brice Videau's avatar
Brice Videau committed
545
		return -EXCIT_ENOMEM;
546 547 548 549
	prod_it->its = new_its;
	prod_it->its[prod_it->count] = added_it;
	prod_it->count = mew_count;
	it->dimension += added_it->dimension;
Brice Videau's avatar
Brice Videau committed
550
	return EXCIT_SUCCESS;
551 552
}

553
static const struct excit_func_table_s excit_product_func_table = {
554 555 556 557 558 559 560 561 562 563 564
	prod_it_alloc,
	prod_it_free,
	prod_it_copy,
	prod_it_next,
	prod_it_peek,
	prod_it_size,
	prod_it_rewind,
	prod_it_split,
	prod_it_nth,
	prod_it_n,
	prod_it_pos
565 566 567 568 569
};

/*--------------------------------------------------------------------*/

struct circular_fifo_s {
570 571 572 573 574
	ssize_t length;
	ssize_t start;
	ssize_t end;
	ssize_t size;
	ssize_t *buffer;
575 576
};

577
static void circular_fifo_add(struct circular_fifo_s *fifo, ssize_t elem)
578 579 580 581 582 583 584 585 586 587 588
{
	if (fifo->size == fifo->length) {
		fifo->start = (fifo->start + 1) % fifo->length;
		fifo->end = (fifo->end + 1) % fifo->length;
	} else {
		fifo->end = (fifo->end + 1) % fifo->length;
		fifo->size++;
	}
	fifo->buffer[fifo->end] = elem;
}

589 590
static void circular_fifo_dump(const struct circular_fifo_s *fifo, 
			       ssize_t *vals)
591
{
592 593
	ssize_t i;
	ssize_t j;
594 595 596 597 598 599 600

	for (i = 0, j = fifo->start; i < fifo->size; i++) {
		vals[i] = fifo->buffer[j];
		j = (j + 1) % fifo->length;
	}
}

601 602 603
struct cons_it_s {
	excit_t it;
	ssize_t n;
604 605 606
	struct circular_fifo_s fifo;
};

607
static int cons_it_alloc(excit_t data)
608
{
609
	data->data = malloc(sizeof(struct cons_it_s));
610
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
611
		return -EXCIT_ENOMEM;
612 613 614 615 616 617 618 619 620
	struct cons_it_s *it = (struct cons_it_s *) data->data;

	it->it = NULL;
	it->n = 0;
	it->fifo.length = 0;
	it->fifo.start = 0;
	it->fifo.end = -1;
	it->fifo.size = 0;
	it->fifo.buffer = NULL;
Brice Videau's avatar
Brice Videau committed
621
	return EXCIT_SUCCESS;
622 623
}

624
static void cons_it_free(excit_t data)
625
{
626
	struct cons_it_s *it = (struct cons_it_s *) data->data;
627

628 629
	excit_free(it->it);
	free(it->fifo.buffer);
630 631 632
	free(data->data);
}

633
static int cons_it_copy(excit_t ddst, const excit_t dsrc)
634
{
635 636 637
	struct cons_it_s *dst = (struct cons_it_s *) ddst->data;
	const struct cons_it_s *src = (const struct cons_it_s *)dsrc->data;
	excit_t copy = excit_dup(src->it);
638 639

	if (!copy)
Brice Videau's avatar
Brice Videau committed
640
		return -EXCIT_EINVAL;
641
	dst->it = copy;
642 643 644 645 646 647
	dst->n = src->n;
	dst->fifo.length = src->fifo.length;
	dst->fifo.start = src->fifo.start;
	dst->fifo.end = src->fifo.end;
	dst->fifo.size = src->fifo.size;
	dst->fifo.buffer =
648
	    (ssize_t *) malloc(src->fifo.length * sizeof(ssize_t));
649
	if (!dst->fifo.buffer) {
650
		excit_free(copy);
Brice Videau's avatar
Brice Videau committed
651
		return -EXCIT_ENOMEM;
652 653 654
	}
	for (int i = 0; i < dst->fifo.length; i++)
		dst->fifo.buffer[i] = src->fifo.buffer[i];
Brice Videau's avatar
Brice Videau committed
655
	return EXCIT_SUCCESS;
656 657
}

658
static int cons_it_size(const excit_t data, ssize_t *size)
659
{
660 661 662
	const struct cons_it_s *it = (const struct cons_it_s *)data->data;
	ssize_t tmp_size = 0;
	int err = excit_size(it->it, &tmp_size);
663 664 665

	if (err)
		return err;
666
	*size = tmp_size - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
667
	return EXCIT_SUCCESS;
668 669
}

670
static int cons_it_split(const excit_t data, ssize_t n, excit_t *results)
671
{
672 673
	ssize_t size;
	int err = cons_it_size(data, &size);
674 675 676 677

	if (err)
		return err;
	if (size < n)
Brice Videau's avatar
Brice Videau committed
678
		return -EXCIT_EDOM;
679
	if (!results)
Brice Videau's avatar
Brice Videau committed
680
		return EXCIT_SUCCESS;
681
	excit_t range = excit_alloc(EXCIT_RANGE);
682 683

	if (!range)
Brice Videau's avatar
Brice Videau committed
684
		return -EXCIT_ENOMEM;
685
	err = excit_range_init(range, 0, size - 1, 1);
686 687
	if (err)
		goto error1;
688
	err = excit_split(range, n, results);
689 690 691 692 693
	if (err)
		goto error1;
	int i;

	for (i = 0; i < n; i++) {
694
		excit_t tmp, tmp2;
695

696
		tmp = excit_dup(data);
697 698 699
		if (!tmp)
			goto error2;
		tmp2 = results[i];
700
		results[i] = excit_alloc(EXCIT_SLICE);
701
		if (!results[i]) {
702
			excit_free(tmp2);
703 704
			goto error2;
		}
705
		err = excit_slice_init(results[i], tmp, tmp2);
706
		if (err) {
707
			excit_free(tmp2);
708 709 710
			goto error2;
		}
	}
711
	excit_free(range);
Brice Videau's avatar
Brice Videau committed
712
	return EXCIT_SUCCESS;
713 714
error2:
	for (; i >= 0; i--)
715
		excit_free(results[i]);
716
error1:
717
	excit_free(range);
718 719 720
	return err;
}

721
static int cons_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
722
{
723 724
	ssize_t size;
	int err = cons_it_size(data, &size);
725 726 727 728

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
729
		return -EXCIT_EDOM;
730 731
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	int dim = it->it->dimension;
732 733

	if (indexes) {
734 735
		for (int i = 0; i < it->n; i++) {
			err = excit_nth(it->it, n + i, indexes + dim * i);
736 737 738 739
			if (err)
				return err;
		}
	}
Brice Videau's avatar
Brice Videau committed
740
	return EXCIT_SUCCESS;
741 742
}

743
static int cons_it_n(const excit_t data, const ssize_t *indexes, ssize_t *n)
744
{
745 746 747
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	ssize_t inner_n, inner_n_tmp;
	int err = excit_n(it->it, indexes, &inner_n);
748 749 750

	if (err)
		return err;
751
	int dim = it->it->dimension;
752

753 754
	for (int i = 1; i < it->n; i++) {
		err = excit_n(it->it, indexes + dim * i, &inner_n_tmp);
755 756 757
		if (err)
			return err;
		if (inner_n_tmp != inner_n + 1)
Brice Videau's avatar
Brice Videau committed
758
			return -EXCIT_EINVAL;
759 760 761
		inner_n = inner_n_tmp;
	}
	if (n)
762
		*n = inner_n - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
763
	return EXCIT_SUCCESS;
764 765
}

766
static int cons_it_pos(const excit_t data, ssize_t *n)
767
{
768 769 770
	ssize_t inner_n;
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
	int err = excit_pos(it->it, &inner_n);
771 772 773 774

	if (err)
		return err;
	if (n)
775
		*n = inner_n - (it->n - 1);
Brice Videau's avatar
Brice Videau committed
776
	return EXCIT_SUCCESS;
777 778
}

779
static int cons_it_peek(const excit_t data, ssize_t *indexes)
780
{
781
	const struct cons_it_s *it = (const struct cons_it_s *) data->data;
782
	int err;
783 784
	int dim = it->it->dimension;
	int n = it->n;
785 786

	if (indexes) {
787 788
		circular_fifo_dump(&it->fifo, indexes);
		err = excit_peek(it->it, indexes + dim * (n - 1));
789
	} else
790
		err = excit_peek(it->it, NULL);
791 792
	if (err)
		return err;
Brice Videau's avatar
Brice Videau committed
793
	return EXCIT_SUCCESS;
794 795
}

796
static int cons_it_next(excit_t data, ssize_t *indexes)
797
{
798
	struct cons_it_s *it = (struct cons_it_s *) data->data;
799
	int err;
800 801
	int dim = it->it->dimension;
	int n = it->n;
802 803

	if (indexes) {
804 805
		circular_fifo_dump(&it->fifo, indexes);
		err = excit_next(it->it, indexes + dim * (n - 1));
806
	} else
807
		err = excit_next(it->it, NULL);
808 809 810 811
	if (err)
		return err;
	if (indexes)
		for (int i = dim * (n - 1); i < dim * n; i++)
812
			circular_fifo_add(&it->fifo, indexes[i]);
Brice Videau's avatar
Brice Videau committed
813
	return EXCIT_SUCCESS;
814 815
}

816
static int cons_it_rewind(excit_t data)
817
{
818 819
	struct cons_it_s *it = (struct cons_it_s *) data->data;
	int err = excit_rewind(it->it);
820 821 822

	if (err)
		return err;
823 824 825
	it->fifo.start = 0;
	it->fifo.end = -1;
	it->fifo.size = 0;
826

827
	for (int i = 0; i < it->n - 1; i++) {
828 829 830
		int err;

		err =
831
		    excit_next(it->it, it->fifo.buffer + it->it->dimension * i);
832 833
		if (err)
			return err;
834 835
		it->fifo.size += it->it->dimension;
		it->fifo.end += it->it->dimension;
836
	}
Brice Videau's avatar
Brice Videau committed
837
	return EXCIT_SUCCESS;
838 839
}

840
int excit_cons_init(excit_t it, excit_t src, ssize_t n)
841
{
842
	ssize_t src_size;
843 844
	int err;

845
	if (!it || it->type != EXCIT_CONS || !src || n <= 0)
Brice Videau's avatar
Brice Videau committed
846
		return -EXCIT_EINVAL;
847
	err = excit_size(src, &src_size);
848 849 850
	if (err)
		return err;
	if (src_size < n)
Brice Videau's avatar
Brice Videau committed
851
		return -EXCIT_EINVAL;
852 853 854 855 856 857 858 859 860 861 862
	struct cons_it_s *cons_it = (struct cons_it_s *) it->data;

	free(cons_it->fifo.buffer);
	excit_free(cons_it->it);
	it->dimension = n * src->dimension;
	cons_it->it = src;
	cons_it->n = n;
	cons_it->fifo.length = src->dimension * (n - 1);
	cons_it->fifo.buffer =
	    (ssize_t *) malloc(cons_it->fifo.length * sizeof(ssize_t));
	if (!cons_it->fifo.buffer)
Brice Videau's avatar
Brice Videau committed
863
		return -EXCIT_ENOMEM;
864
	err = cons_it_rewind(it);
865
	if (err) {
866
		free(cons_it->fifo.buffer);
867 868
		return err;
	}
Brice Videau's avatar
Brice Videau committed
869
	return EXCIT_SUCCESS;
870 871
}

872
static const struct excit_func_table_s excit_cons_func_table = {
873 874 875 876 877 878 879 880 881 882 883
	cons_it_alloc,
	cons_it_free,
	cons_it_copy,
	cons_it_next,
	cons_it_peek,
	cons_it_size,
	cons_it_rewind,
	cons_it_split,
	cons_it_nth,
	cons_it_n,
	cons_it_pos
884 885 886 887
};

/*--------------------------------------------------------------------*/

888 889 890 891
struct repeat_it_s {
	excit_t it;
	ssize_t n;
	ssize_t counter;
892 893
};

894
static int repeat_it_alloc(excit_t data)
895
{
896
	data->data = malloc(sizeof(struct repeat_it_s));
897
	if (!data->data)
Brice Videau's avatar
Brice Videau committed
898
		return -EXCIT_ENOMEM;
899
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
900

901 902 903
	it->it = NULL;
	it->n = 0;
	it->counter = 0;
Brice Videau's avatar
Brice Videau committed
904
	return EXCIT_SUCCESS;
905 906
}

907
static void repeat_it_free(excit_t data)
908
{
909
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
910

911
	excit_free(it->it);
912 913 914
	free(data->data);
}

915
static int repeat_it_copy(excit_t ddst, const excit_t dsrc)
916
{
917 918 919
	struct repeat_it_s *dst = (struct repeat_it_s *) ddst->data;
	const struct repeat_it_s *src = (const struct repeat_it_s *)dsrc->data;
	excit_t copy = excit_dup(src->it);
920 921

	if (!copy)
Brice Videau's avatar
Brice Videau committed
922
		return -EXCIT_EINVAL;
923
	dst->it = copy;
924 925
	dst->n = src->n;
	dst->counter = src->counter;
Brice Videau's avatar
Brice Videau committed
926
	return EXCIT_SUCCESS;
927 928
}

929
static int repeat_it_peek(const excit_t data, ssize_t *indexes)
930
{
931
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
932

933
	return excit_peek(it->it, indexes);
934 935
}

936
static int repeat_it_next(excit_t data, ssize_t *indexes)
937
{
938
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
939

940 941 942 943 944
	it->counter++;
	if (it->counter < it->n)
		return excit_peek(it->it, indexes);
	it->counter = 0;
	return excit_next(it->it, indexes);
945 946
}

947
static int repeat_it_size(const excit_t data, ssize_t *size)
948
{
949 950
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
	int err = excit_size(it->it, size);
951 952 953

	if (err)
		return err;
954
	*size *= it->n;
Brice Videau's avatar
Brice Videau committed
955
	return EXCIT_SUCCESS;
956 957
}

958
static int repeat_it_rewind(excit_t data)
959
{
960
	struct repeat_it_s *it = (struct repeat_it_s *) data->data;
961

962 963
	it->counter = 0;
	return excit_rewind(it->it);
964 965
}

966
static int repeat_it_nth(const excit_t data, ssize_t n, ssize_t *val)
967
{
968 969
	ssize_t size;
	int err = repeat_it_size(data, &size);
970 971 972 973

	if (err)
		return err;
	if (n < 0 || n >= size)
Brice Videau's avatar
Brice Videau committed
974
		return -EXCIT_EDOM;
975
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
976

977
	return excit_nth(it->it, n / it->n, val);
978 979
}

980
static int repeat_it_pos(const excit_t data, ssize_t *n)
981
{
982 983 984
	ssize_t inner_n;
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
	int err = excit_pos(it->it, &inner_n);
985 986 987 988

	if (err)
		return err;
	if (n)
989
		*n = inner_n * it->n + it->counter;
Brice Videau's avatar
Brice Videau committed
990
	return EXCIT_SUCCESS;
991 992
}

993
static int repeat_it_split(const excit_t data, ssize_t n, excit_t *results)
994
{
995 996
	const struct repeat_it_s *it = (const struct repeat_it_s *) data->data;
	int err = excit_split(it->it, n, results);
997 998 999 1000

	if (err)
		return err;
	if (!results)
Brice Videau's avatar
Brice Videau committed
1001
		return EXCIT_SUCCESS;
1002
	for (int i = 0; i < n; i++) {
1003
		excit_t tmp;
1004 1005

		tmp = results[i];
1006
		results[i] = excit_alloc(EXCIT_REPEAT);
1007
		if (!results[i]) {