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