1219019Sgabor/* $FreeBSD$ */
2219019Sgabor/*	$NetBSD: citrus_mapper_serial.c,v 1.2 2003/07/12 15:39:20 tshiozak Exp $	*/
3219019Sgabor
4219019Sgabor/*-
5219019Sgabor * Copyright (c)2003 Citrus Project,
6219019Sgabor * All rights reserved.
7219019Sgabor *
8219019Sgabor * Redistribution and use in source and binary forms, with or without
9219019Sgabor * modification, are permitted provided that the following conditions
10219019Sgabor * are met:
11219019Sgabor * 1. Redistributions of source code must retain the above copyright
12219019Sgabor *    notice, this list of conditions and the following disclaimer.
13219019Sgabor * 2. Redistributions in binary form must reproduce the above copyright
14219019Sgabor *    notice, this list of conditions and the following disclaimer in the
15219019Sgabor *    documentation and/or other materials provided with the distribution.
16219019Sgabor *
17219019Sgabor * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18219019Sgabor * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19219019Sgabor * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20219019Sgabor * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21219019Sgabor * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22219019Sgabor * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23219019Sgabor * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24219019Sgabor * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25219019Sgabor * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26219019Sgabor * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27219019Sgabor * SUCH DAMAGE.
28219019Sgabor */
29219019Sgabor
30219019Sgabor#include <sys/cdefs.h>
31219019Sgabor#include <sys/queue.h>
32219019Sgabor
33219019Sgabor#include <assert.h>
34219019Sgabor#include <errno.h>
35219019Sgabor#include <limits.h>
36219019Sgabor#include <stdio.h>
37219019Sgabor#include <stdlib.h>
38219019Sgabor#include <string.h>
39219019Sgabor
40219019Sgabor#include "citrus_namespace.h"
41219019Sgabor#include "citrus_types.h"
42219019Sgabor#include "citrus_bcs.h"
43219019Sgabor#include "citrus_module.h"
44219019Sgabor#include "citrus_region.h"
45219019Sgabor#include "citrus_memstream.h"
46219019Sgabor#include "citrus_mmap.h"
47219019Sgabor#include "citrus_hash.h"
48219019Sgabor#include "citrus_mapper.h"
49219019Sgabor#include "citrus_mapper_serial.h"
50219019Sgabor
51219019Sgabor/* ---------------------------------------------------------------------- */
52219019Sgabor
53219019Sgabor_CITRUS_MAPPER_DECLS(mapper_serial);
54219019Sgabor_CITRUS_MAPPER_DEF_OPS(mapper_serial);
55219019Sgabor
56219019Sgabor#define _citrus_mapper_parallel_mapper_init		\
57219019Sgabor	_citrus_mapper_serial_mapper_init
58219019Sgabor#define _citrus_mapper_parallel_mapper_uninit		\
59219019Sgabor	_citrus_mapper_serial_mapper_uninit
60219019Sgabor#define _citrus_mapper_parallel_mapper_init_state	\
61219019Sgabor	_citrus_mapper_serial_mapper_init_state
62219019Sgaborstatic int	_citrus_mapper_parallel_mapper_convert(
63219019Sgabor		    struct _citrus_mapper * __restrict, _index_t * __restrict,
64219019Sgabor		    _index_t, void * __restrict);
65219019Sgabor_CITRUS_MAPPER_DEF_OPS(mapper_parallel);
66219019Sgabor#undef _citrus_mapper_parallel_mapper_init
67219019Sgabor#undef _citrus_mapper_parallel_mapper_uninit
68219019Sgabor#undef _citrus_mapper_parallel_mapper_init_state
69219019Sgabor
70219019Sgabor
71219019Sgabor/* ---------------------------------------------------------------------- */
72219019Sgabor
73219019Sgaborstruct maplink {
74219019Sgabor	STAILQ_ENTRY(maplink)	 ml_entry;
75219019Sgabor	struct _mapper		*ml_mapper;
76219019Sgabor};
77219019SgaborSTAILQ_HEAD(maplist, maplink);
78219019Sgabor
79219019Sgaborstruct _citrus_mapper_serial {
80219019Sgabor	struct maplist		 sr_mappers;
81219019Sgabor};
82219019Sgabor
83219019Sgaborint
84219019Sgabor_citrus_mapper_serial_mapper_getops(struct _citrus_mapper_ops *ops)
85219019Sgabor{
86219019Sgabor
87219019Sgabor	memcpy(ops, &_citrus_mapper_serial_mapper_ops,
88219019Sgabor	    sizeof(_citrus_mapper_serial_mapper_ops));
89219019Sgabor
90219019Sgabor	return (0);
91219019Sgabor}
92219019Sgabor
93219019Sgaborint
94219019Sgabor_citrus_mapper_parallel_mapper_getops(struct _citrus_mapper_ops *ops)
95219019Sgabor{
96219019Sgabor
97219019Sgabor	memcpy(ops, &_citrus_mapper_parallel_mapper_ops,
98219019Sgabor	    sizeof(_citrus_mapper_parallel_mapper_ops));
99219019Sgabor
100219019Sgabor	return (0);
101219019Sgabor}
102219019Sgabor
103219019Sgaborstatic void
104219019Sgaboruninit(struct _citrus_mapper_serial *sr)
105219019Sgabor{
106219019Sgabor	struct maplink *ml;
107219019Sgabor
108219019Sgabor	while ((ml = STAILQ_FIRST(&sr->sr_mappers)) != NULL) {
109219019Sgabor		STAILQ_REMOVE_HEAD(&sr->sr_mappers, ml_entry);
110219019Sgabor		_mapper_close(ml->ml_mapper);
111219019Sgabor		free(ml);
112219019Sgabor	}
113219019Sgabor}
114219019Sgabor
115219019Sgaborstatic int
116219019Sgaborparse_var(struct _citrus_mapper_area *__restrict ma,
117219019Sgabor    struct _citrus_mapper_serial *sr, struct _memstream *ms)
118219019Sgabor{
119219019Sgabor	struct _region r;
120219019Sgabor	struct maplink *ml;
121219019Sgabor	char mapname[PATH_MAX];
122219019Sgabor	int ret;
123219019Sgabor
124219019Sgabor	STAILQ_INIT(&sr->sr_mappers);
125219019Sgabor	while (1) {
126219019Sgabor		/* remove beginning white spaces */
127219019Sgabor		_memstream_skip_ws(ms);
128219019Sgabor		if (_memstream_iseof(ms))
129219019Sgabor			break;
130219019Sgabor		/* cut down a mapper name */
131219019Sgabor		_memstream_chr(ms, &r, ',');
132219019Sgabor		snprintf(mapname, sizeof(mapname), "%.*s",
133219019Sgabor		    (int)_region_size(&r), (char *)_region_head(&r));
134219019Sgabor		/* remove trailing white spaces */
135219019Sgabor		mapname[_bcs_skip_nonws(mapname)-mapname] = '\0';
136219019Sgabor		/* create a new mapper record */
137219019Sgabor		ml = malloc(sizeof(*ml));
138219019Sgabor		if (ml == NULL)
139219019Sgabor			return (errno);
140219019Sgabor		ret = _mapper_open(ma, &ml->ml_mapper, mapname);
141219019Sgabor		if (ret) {
142219019Sgabor			free(ml);
143219019Sgabor			return (ret);
144219019Sgabor		}
145219019Sgabor		/* support only 1:1 and stateless converter */
146219019Sgabor		if (_mapper_get_src_max(ml->ml_mapper) != 1 ||
147219019Sgabor		    _mapper_get_dst_max(ml->ml_mapper) != 1 ||
148219019Sgabor		    _mapper_get_state_size(ml->ml_mapper) != 0) {
149219019Sgabor			free(ml);
150219019Sgabor			return (EINVAL);
151219019Sgabor		}
152219019Sgabor		STAILQ_INSERT_TAIL(&sr->sr_mappers, ml, ml_entry);
153219019Sgabor	}
154219019Sgabor	return (0);
155219019Sgabor}
156219019Sgabor
157219019Sgaborstatic int
158219019Sgabor/*ARGSUSED*/
159219019Sgabor_citrus_mapper_serial_mapper_init(struct _citrus_mapper_area *__restrict ma __unused,
160219019Sgabor    struct _citrus_mapper * __restrict cm, const char * __restrict dir __unused,
161219019Sgabor    const void * __restrict var, size_t lenvar,
162219019Sgabor    struct _citrus_mapper_traits * __restrict mt, size_t lenmt)
163219019Sgabor{
164219019Sgabor	struct _citrus_mapper_serial *sr;
165219019Sgabor	struct _memstream ms;
166219019Sgabor	struct _region r;
167219019Sgabor
168219019Sgabor	if (lenmt < sizeof(*mt))
169219019Sgabor		return (EINVAL);
170219019Sgabor
171219019Sgabor	sr = malloc(sizeof(*sr));
172219019Sgabor	if (sr == NULL)
173219019Sgabor		return (errno);
174219019Sgabor
175219019Sgabor	_region_init(&r, __DECONST(void *, var), lenvar);
176219019Sgabor	_memstream_bind(&ms, &r);
177219019Sgabor	if (parse_var(ma, sr, &ms)) {
178219019Sgabor		uninit(sr);
179219019Sgabor		free(sr);
180219019Sgabor		return (EINVAL);
181219019Sgabor	}
182219019Sgabor	cm->cm_closure = sr;
183219019Sgabor	mt->mt_src_max = mt->mt_dst_max = 1;	/* 1:1 converter */
184219019Sgabor	mt->mt_state_size = 0;			/* stateless */
185219019Sgabor
186219019Sgabor	return (0);
187219019Sgabor}
188219019Sgabor
189219019Sgaborstatic void
190219019Sgabor/*ARGSUSED*/
191219019Sgabor_citrus_mapper_serial_mapper_uninit(struct _citrus_mapper *cm)
192219019Sgabor{
193219019Sgabor
194219019Sgabor	if (cm && cm->cm_closure) {
195219019Sgabor		uninit(cm->cm_closure);
196219019Sgabor		free(cm->cm_closure);
197219019Sgabor	}
198219019Sgabor}
199219019Sgabor
200219019Sgaborstatic int
201219019Sgabor/*ARGSUSED*/
202219019Sgabor_citrus_mapper_serial_mapper_convert(struct _citrus_mapper * __restrict cm,
203219019Sgabor    _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
204219019Sgabor{
205219019Sgabor	struct _citrus_mapper_serial *sr;
206219019Sgabor	struct maplink *ml;
207219019Sgabor	int ret;
208219019Sgabor
209219019Sgabor	sr = cm->cm_closure;
210219019Sgabor	STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
211219019Sgabor		ret = _mapper_convert(ml->ml_mapper, &src, src, NULL);
212219019Sgabor		if (ret != _MAPPER_CONVERT_SUCCESS)
213219019Sgabor			return (ret);
214219019Sgabor	}
215219019Sgabor	*dst = src;
216219019Sgabor	return (_MAPPER_CONVERT_SUCCESS);
217219019Sgabor}
218219019Sgabor
219219019Sgaborstatic int
220219019Sgabor/*ARGSUSED*/
221219019Sgabor_citrus_mapper_parallel_mapper_convert(struct _citrus_mapper * __restrict cm,
222219019Sgabor    _index_t * __restrict dst, _index_t src, void * __restrict ps __unused)
223219019Sgabor{
224219019Sgabor	struct _citrus_mapper_serial *sr;
225219019Sgabor	struct maplink *ml;
226219019Sgabor	_index_t tmp;
227219019Sgabor	int ret;
228219019Sgabor
229219019Sgabor	sr = cm->cm_closure;
230219019Sgabor	STAILQ_FOREACH(ml, &sr->sr_mappers, ml_entry) {
231219019Sgabor		ret = _mapper_convert(ml->ml_mapper, &tmp, src, NULL);
232219019Sgabor		if (ret == _MAPPER_CONVERT_SUCCESS) {
233219019Sgabor			*dst = tmp;
234219019Sgabor			return (_MAPPER_CONVERT_SUCCESS);
235219019Sgabor		} else if (ret == _MAPPER_CONVERT_ILSEQ)
236219019Sgabor			return (_MAPPER_CONVERT_ILSEQ);
237219019Sgabor	}
238219019Sgabor	return (_MAPPER_CONVERT_NONIDENTICAL);
239219019Sgabor}
240219019Sgabor
241219019Sgaborstatic void
242219019Sgabor/*ARGSUSED*/
243219019Sgabor_citrus_mapper_serial_mapper_init_state(void)
244219019Sgabor{
245219019Sgabor
246219019Sgabor}
247