aboutsummaryrefslogtreecommitdiff
path: root/lib/iter/super.c
blob: 57c87427036959592cd01287dc8b83eba04039c4 (plain)
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
/* ****************************************************************************
 * iter/super.c -- super-iterator, for super-iterating.
 * Copyright (C) 2018 Thomas "Cakeisalie5" Touhey <thomas@touhey.fr>
 *
 * This file is part of libcasio.
 * libcasio is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3.0 of the License,
 * or (at your option) any later version.
 *
 * libcasio is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with libcasio; if not, see <http://www.gnu.org/licenses/>.
 * ************************************************************************* */
#include "../internals.h"

typedef struct {
	int i, len;
	casio_iter_t *its[2];
} supercookie_t;

/* `next_super()`: next element from the super iterator. */

CASIO_LOCAL int next_super(supercookie_t *cookie, void **ptr)
{
	int err;

	if (cookie->i == cookie->len)
		return (casio_error_iter);

	while (cookie->i < cookie->len - 1) {
		if ((err = casio_next(cookie->its[cookie->i], ptr))
		 != casio_error_iter)
			return (err);

		casio_end(cookie->its[cookie->i++]);
	}

	if ((err = casio_next(cookie->its[cookie->i], ptr)) != casio_error_iter)
		return (err);

	casio_end(cookie->its[cookie->i++]);
	return (casio_error_iter);
}

/* `end_super()`: end the super-iterator. */

CASIO_LOCAL void end_super(supercookie_t *cookie)
{
	int i;

	for (i = cookie->i; i < cookie->len; i++)
		casio_end(cookie->its[i]);
	free(cookie);
}

/* Callbacks. */

CASIO_LOCAL casio_iter_funcs_t const super_funcs = {
	(casio_next_t *)next_super,
	NULL,
	(casio_end_t *)end_super
};

/**
 *	casio_combine_iterator:
 *	Make a super iterator.
 *
 *	@arg	iterp		the super-iterator to create.
 *	@arg	first		the first iterator to put into the super-iterator.
 *	@arg	second		the second one.
 *	@return				the error code (0 if ok).
 */

int CASIO_EXPORT casio_combine_iterators(casio_iter_t **iterp,
	casio_iter_t *first, casio_iter_t *second)
{
	supercookie_t *cookie;

	if (!(cookie = malloc(sizeof(supercookie_t)))) {
		casio_end(first);
		casio_end(second);
		return (casio_error_alloc);
	}

	cookie->len = 2;
	cookie->i = 0;
	cookie->its[0] = first;
	cookie->its[1] = second;

	return (casio_iter(iterp, cookie, &super_funcs));
}