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