slice.c 3.83 KB
Newer Older
1
#include "dev/excit.h"
2 3
#include "slice.h"

4
static int slice_it_alloc(excit_t data)
5
{
6 7 8 9 10
	struct slice_it_s *it = (struct slice_it_s *)data->data;

	it->src = NULL;
	it->indexer = NULL;
	return EXCIT_SUCCESS;
11 12
}

13
static void slice_it_free(excit_t data)
14
{
15 16 17 18
	struct slice_it_s *it = (struct slice_it_s *)data->data;

	excit_free(it->src);
	excit_free(it->indexer);
19 20
}

21
static int slice_it_copy(excit_t dst, const excit_t src)
22
{
23 24 25 26 27 28 29 30 31 32 33 34
	const struct slice_it_s *it = (const struct slice_it_s *)src->data;
	struct slice_it_s *result = (struct slice_it_s *)dst->data;

	result->src = excit_dup(it->src);
	if (!result->src)
		return -EXCIT_ENOMEM;
	result->indexer = excit_dup(it->indexer);
	if (!result->indexer) {
		excit_free(it->src);
		return -EXCIT_ENOMEM;
	}
	return EXCIT_SUCCESS;
35 36
}

37
static int slice_it_next(excit_t data, ssize_t *indexes)
38
{
39 40 41 42 43 44 45
	struct slice_it_s *it = (struct slice_it_s *)data->data;
	ssize_t n;
	int err = excit_next(it->indexer, &n);

	if (err)
		return err;
	return excit_nth(it->src, n, indexes);
46 47
}

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

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

59
static int slice_it_size(const excit_t data, ssize_t *size)
60
{
61 62 63
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;

	return excit_size(it->indexer, size);
64 65
}

66
static int slice_it_rewind(excit_t data)
67
{
68
	struct slice_it_s *it = (struct slice_it_s *)data->data;
69

70
	return excit_rewind(it->indexer);
71 72
}

73
static int slice_it_nth(const excit_t data, ssize_t n, ssize_t *indexes)
74
{
75 76 77 78 79 80 81
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t p;
	int err = excit_nth(it->indexer, n, &p);

	if (err)
		return err;
	return excit_nth(it->src, p, indexes);
82 83
}

84 85
static int slice_it_rank(const excit_t data, const ssize_t *indexes,
			 ssize_t *n)
86
{
87 88 89 90 91 92 93
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	ssize_t inner_n;
	int err = excit_rank(it->src, indexes, &inner_n);

	if (err)
		return err;
	return excit_rank(it->indexer, &inner_n, n);
94 95
}

96
static int slice_it_pos(const excit_t data, ssize_t *n)
97
{
98 99 100
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;

	return excit_pos(it->indexer, n);
101 102
}

103
static int slice_it_split(const excit_t data, ssize_t n, excit_t *results)
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
	const struct slice_it_s *it = (const struct slice_it_s *)data->data;
	int err = excit_split(it->indexer, n, results);

	if (err)
		return err;
	if (!results)
		return EXCIT_SUCCESS;
	for (int i = 0; i < n; i++) {
		excit_t tmp;
		excit_t tmp2;

		tmp = results[i];
		results[i] = excit_alloc(EXCIT_SLICE);
		if (!results[i]) {
			excit_free(tmp);
			err = -EXCIT_ENOMEM;
			goto error;
		}
		tmp2 = excit_dup(it->src);
		if (!tmp2) {
			excit_free(tmp);
			err = -EXCIT_ENOMEM;
			goto error;
		}
129
		err = excit_slice_init(results[i], tmp2, tmp);
130 131 132 133 134 135 136
		if (err) {
			excit_free(tmp);
			excit_free(tmp2);
			goto error;
		}
	}
	return EXCIT_SUCCESS;
137
error:
138 139 140
	for (int i = 0; i < n; i++)
		excit_free(results[i]);
	return err;
141 142
}

143 144 145 146 147 148 149 150 151 152 153 154 155 156
struct excit_func_table_s excit_slice_func_table = {
	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_rank,
	slice_it_pos
};

157 158
int excit_slice_init(excit_t it, excit_t src, excit_t indexer)
{
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
	if (!it || it->type != EXCIT_SLICE || !src || !indexer
	    || indexer->dimension != 1)
		return -EXCIT_EINVAL;
	struct slice_it_s *slice_it = (struct slice_it_s *)it->data;
	ssize_t size_src;
	ssize_t size_indexer;
	int err = excit_size(src, &size_src);

	if (err)
		return err;
	err = excit_size(indexer, &size_indexer);
	if (err)
		return err;
	if (size_indexer > size_src)
		return -EXCIT_EDOM;
	slice_it->src = src;
	slice_it->indexer = indexer;
	it->dimension = src->dimension;
	return EXCIT_SUCCESS;
178 179
}