1/* $FreeBSD$ */
2/*	$NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $	*/
3
4/*-
5 * Copyright (c)2003 Citrus Project,
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31#include <sys/queue.h>
32
33#include <assert.h>
34#include <errno.h>
35#include <limits.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39
40#include "citrus_namespace.h"
41#include "citrus_types.h"
42#include "citrus_bcs.h"
43#include "citrus_module.h"
44#include "citrus_region.h"
45#include "citrus_memstream.h"
46#include "citrus_mmap.h"
47#include "citrus_hash.h"
48#include "citrus_mapper.h"
49#include "citrus_mapper_serial.h"
50
51/* ---------------------------------------------------------------------- */
52
53_CITRUS_MAPPER_DECLS(mapper_serial);
54_CITRUS_MAPPER_DEF_OPS(mapper_serial);
55
56#define _citrus_mapper_parallel_mapper_init		\
57	_citrus_mapper_serial_mapper_init
58#define _citrus_mapper_parallel_mapper_uninit		\
59	_citrus_mapper_serial_mapper_uninit
60#define _citrus_mapper_parallel_mapper_init_state	\
61	_citrus_mapper_serial_mapper_init_state
62static int	_citrus_mapper_parallel_mapper_convert(
63		    struct _citrus_mapper * __restrict, _index_t * __restrict,
64		    _index_t, void * __restrict);
65_CITRUS_MAPPER_DEF_OPS(mapper_parallel);
66#undef _citrus_mapper_parallel_mapper_init
67#undef _citrus_mapper_parallel_mapper_uninit
68#undef _citrus_mapper_parallel_mapper_init_state
69
70
71/* ---------------------------------------------------------------------- */
72
73struct maplink {
74	STAILQ_ENTRY(maplink)	 ml_entry;
75	struct _mapper		*ml_mapper;
76};
77STAILQ_HEAD(maplist, maplink);
78
79struct _citrus_mapper_serial {
80	struct maplist		 sr_mappers;
81};
82
83int
84_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops)
85{
86
87	memcpy(ops, &_citrus_mapper_serial_mapper_ops,
88	    sizeof(_citrus_mapper_serial_mapper_ops));
89
90	return (0);
91}
92
93int
94_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops)
95{
96
97	memcpy(ops, &_citrus_mapper_parallel_mapper_ops,
98	    sizeof(_citrus_mapper_parallel_mapper_ops));
99
100	return (0);
101}
102
103static void
104uninit(struct _citrus_mapper_serial *sr)
105{
106	struct maplink *ml;
107
108	while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) {
109		STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry);
110		_mapper_close(ml->ml_mapper);
111		free(ml);
112	}
113}
114
115static int
116parse_var(struct _citrus_mapper_area *__restrict ma,
117    struct _citrus_mapper_serial *sr, struct _memstream *ms)
118{
119	struct _region r;
120	struct maplink *ml;
121	char mapname[PATH_MAX];
122	int ret;
123
124	STAILQ_INIT(&sr->sr_mappers);
125	while (1) {
126		/* remove beginning white spaces */
127		_memstream_skip_ws(ms);
128		if (_memstream_iseof(ms))
129			break;
130		/* cut down a mapper name */
131		_memstream_chr(ms, &r, ',');
132		snprintf(mapname, sizeof(mapname), "%.*s",
133		    (int)_region_size(&r), (char *)_region_head(&r));
134		/* remove trailing white spaces */
135		mapname[_bcs_skip_nonws(mapname)-mapname] = '\0';
136		/* create a new mapper record */
137		ml = malloc(sizeof(*ml));
138		if (ml == NULL)
139			return (errno);
140		ret = _mapper_open(ma, &ml->ml_mapper, mapname);
141		if (ret) {
142			free(ml);
143			return (ret);
144		}
145		/* support only 1:1 and stateless converter */
146		if (_mapper_get_src_max(ml->ml_mapper) != 1 ||
147		    _mapper_get_dst_max(ml->ml_mapper) != 1 ||
148		    _mapper_get_state_size(ml->ml_mapper) != 0) {
149			free(ml);
150			return (EINVAL);
151		}
152		STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry);
153	}
154	return (0);
155}
156
157static int
158/*ARGSUSED*/
159_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
160    struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused,
161    const void * __restrict var, size_t lenvar,
162    struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
163{
164	struct _citrus_mapper_serial *sr;
165	struct _memstream ms;
166	struct _region r;
167
168	if (lenmt < sizeof(*mt))
169		return (EINVAL);
170
171	sr = malloc(sizeof(*sr));
172	if (sr == NULL)
173		return (errno);
174
175	_region_init(&r, __DECONST(void *, var), lenvar);
176	_memstream_bind(&ms, &r);
177	if (parse_var(ma, sr, &ms)) {
178		uninit(sr);
179		free(sr);
180		return (EINVAL);
181	}
182	cm->cm_closure = sr;
183	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
184	mt->mt_state_size = 0;			/* stateless */
185
186	return (0);
187}
188
189static void
190/*ARGSUSED*/
191_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm)
192{
193
194	if (cm && cm->cm_closure) {
195		uninit(cm->cm_closure);
196		free(cm->cm_closure);
197	}
198}
199
200static int
201/*ARGSUSED*/
202_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm,
203    _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
204{
205	struct _citrus_mapper_serial *sr;
206	struct maplink *ml;
207	int ret;
208
209	sr = cm->cm_closure;
210	STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
211		ret = _mapper_convert(ml->ml_mapper, &src, src, NULL);
212		if (ret != _MAPPER_CONVERT_SUCCESS)
213			return (ret);
214	}
215	*dst = src;
216	return (_MAPPER_CONVERT_SUCCESS);
217}
218
219static int
220/*ARGSUSED*/
221_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm,
222    _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
223{
224	struct _citrus_mapper_serial *sr;
225	struct maplink *ml;
226	_index_t tmp;
227	int ret;
228
229	sr = cm->cm_closure;
230	STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
231		ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL);
232		if (ret == _MAPPER_CONVERT_SUCCESS) {
233			*dst = tmp;
234			return (_MAPPER_CONVERT_SUCCESS);
235		} else if (ret == _MAPPER_CONVERT_ILSEQ)
236			return (_MAPPER_CONVERT_ILSEQ);
237	}
238	return (_MAPPER_CONVERT_NONIDENTICAL);
239}
240
241static void
242/*ARGSUSED*/
243_citrus_mapper_serial_mapper_init_state(void)
244{
245
246}
247