xref: /netbsd-src/lib/libc/citrus/modules/citrus_johab.c (revision 466a16a118933bd295a8a104f095714fadf9cf68)
1 /* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $ */
2 
3 /*-
4  * Copyright (c)2006 Citrus Project,
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 #include <sys/cdefs.h>
29 #if defined(LIBC_SCCS) && !defined(lint)
30 __RCSID("$NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $");
31 #endif /* LIBC_SCCS and not lint */
32 
33 #include <sys/types.h>
34 #include <assert.h>
35 #include <errno.h>
36 #include <string.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stddef.h>
41 #include <wchar.h>
42 #include <limits.h>
43 
44 #include "citrus_namespace.h"
45 #include "citrus_types.h"
46 #include "citrus_bcs.h"
47 #include "citrus_module.h"
48 #include "citrus_ctype.h"
49 #include "citrus_stdenc.h"
50 #include "citrus_johab.h"
51 
52 /* ----------------------------------------------------------------------
53  * private stuffs used by templates
54  */
55 
56 typedef struct {
57 	int chlen;
58 	char ch[2];
59 } _JOHABState;
60 
61 typedef struct {
62 	int dummy;
63 } _JOHABEncodingInfo;
64 
65 typedef struct {
66 	_JOHABEncodingInfo	ei;
67 	struct {
68 		/* for future multi-locale facility */
69 		_JOHABState	s_mblen;
70 		_JOHABState	s_mbrlen;
71 		_JOHABState	s_mbrtowc;
72 		_JOHABState	s_mbtowc;
73 		_JOHABState	s_mbsrtowcs;
74 		_JOHABState	s_wcrtomb;
75 		_JOHABState	s_wcsrtombs;
76 		_JOHABState	s_wctomb;
77 	} states;
78 } _JOHABCTypeInfo;
79 
80 #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
81 #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
82 
83 #define _FUNCNAME(m)			_citrus_JOHAB_##m
84 #define _ENCODING_INFO			_JOHABEncodingInfo
85 #define _CTYPE_INFO			_JOHABCTypeInfo
86 #define _ENCODING_STATE			_JOHABState
87 #define _ENCODING_MB_CUR_MAX(_ei_)		2
88 #define _ENCODING_IS_STATE_DEPENDENT		0
89 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
90 
91 
92 static __inline void
93 /*ARGSUSED*/
94 _citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei,
95 	_JOHABState * __restrict psenc)
96 {
97 	/* ei may be null */
98 	_DIAGASSERT(psenc != NULL);
99 
100 	psenc->chlen = 0;
101 }
102 
103 static __inline void
104 /*ARGSUSED*/
105 _citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei,
106 	void * __restrict pspriv,
107 	const _JOHABState * __restrict psenc)
108 {
109 	/* ei may be null */
110 	_DIAGASSERT(pspriv != NULL);
111 	_DIAGASSERT(psenc != NULL);
112 
113 	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
114 }
115 
116 static __inline void
117 /*ARGSUSED*/
118 _citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei,
119 	_JOHABState * __restrict psenc,
120 	const void * __restrict pspriv)
121 {
122 	/* ei may be null */
123 	_DIAGASSERT(psenc != NULL);
124 	_DIAGASSERT(pspriv != NULL);
125 
126 	memcpy((void *)psenc, pspriv, sizeof(*psenc));
127 }
128 
129 static void
130 /*ARGSUSED*/
131 _citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei)
132 {
133 	/* ei may be null */
134 }
135 
136 static int
137 /*ARGSUSED*/
138 _citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei,
139 	const void * __restrict var, size_t lenvar)
140 {
141 	/* ei may be null */
142 	return 0;
143 }
144 
145 static __inline int
146 ishangul(int l, int t)
147 {
148 
149 	return (l >= 0x84 && l <= 0xD3) &&
150 	      ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE));
151 }
152 
153 static __inline int
154 isuda(int l, int t)
155 {
156 	return (l == 0xD8) &&
157 	       ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE));
158 }
159 
160 static __inline int
161 ishanja(int l, int t)
162 {
163 	return ((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
164 	       ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE));
165 }
166 
167 static int
168 /*ARGSUSED*/
169 _citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
170 	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
171 	_JOHABState * __restrict psenc, size_t * __restrict nresult)
172 {
173 	const char *s0;
174 	int l, t;
175 
176 	/* ei may be unused */
177 	_DIAGASSERT(s != NULL);
178 	_DIAGASSERT(psenc != NULL);
179 	_DIAGASSERT(nresult != 0);
180 
181 	if (*s == NULL) {
182 		_citrus_JOHAB_init_state(ei, psenc);
183 		*nresult = _ENCODING_IS_STATE_DEPENDENT;
184 		return 0;
185 	}
186 	s0 = *s;
187 
188 	switch (psenc->chlen) {
189 	case 0:
190 		if (n-- < 1)
191 			goto restart;
192 		l = *s0++ & 0xFF;
193 		if (l <= 0x7F) {
194 			if (pwc != NULL)
195 				*pwc = (wchar_t)l;
196 			*nresult = (l == 0) ? 0 : 1;
197 			*s = s0;
198 			return 0;
199 		}
200 		psenc->ch[psenc->chlen++] = l;
201 		break;
202 	case 1:
203 		l = psenc->ch[0] & 0xFF;
204 		break;
205 	default:
206 		return EINVAL;
207 	}
208 	if (n-- < 1) {
209 restart:
210 		*nresult = (size_t)-2;
211 		*s = s0;
212 		return 0;
213 	}
214 	t = *s0++ & 0xFF;
215 	if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
216 		*nresult = (size_t)-1;
217 		return EILSEQ;
218 	}
219 	if (pwc != NULL)
220 		*pwc = (wchar_t)(l << 8 | t);
221 	*nresult = s0 - *s;
222 	*s = s0;
223 	psenc->chlen = 0;
224 
225 	return 0;
226 }
227 
228 static int
229 /*ARGSUSED*/
230 _citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei,
231 	char * __restrict s, size_t n, wchar_t wc,
232 	_JOHABState * __restrict psenc, size_t * __restrict nresult)
233 {
234 	int l, t;
235 
236 	/* ei may be unused */
237 	_DIAGASSERT(s != NULL);
238 	_DIAGASSERT(psenc != NULL);
239 	_DIAGASSERT(nresult != NULL);
240 
241 	if (psenc->chlen != 0)
242 		return EINVAL;
243 
244 	/* XXX assume wchar_t as int */
245 	if ((uint32_t)wc <= 0x7F) {
246 		if (n < 1)
247 			goto e2big;
248 		*s = wc & 0xFF;
249 		*nresult = 1;
250 	} else if ((uint32_t)wc <= 0xFFFF) {
251 		if (n < 2) {
252 e2big:
253 			*nresult = (size_t)-1;
254 			return E2BIG;
255 		}
256 		l = (wc >> 8) & 0xFF;
257 		t = wc & 0xFF;
258 		if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
259 			goto ilseq;
260 		*s++ = l;
261 		*s = t;
262 		*nresult = 2;
263 	} else {
264 ilseq:
265 		*nresult = (size_t)-1;
266 		return EILSEQ;
267 	}
268 	return 0;
269 
270 }
271 
272 static __inline int
273 /*ARGSUSED*/
274 _citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei,
275 	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
276 {
277 	int m, l, t, linear;
278 
279 	/* ei may be unused */
280 	_DIAGASSERT(csid != NULL);
281 	_DIAGASSERT(idx != NULL);
282 
283 	/* XXX assume wchar_t as int */
284 	if ((uint32_t)wc <= 0x7F) {
285 		*idx = (_index_t)wc;
286 		*csid = 0;
287 	} else if ((uint32_t)wc <= 0xFFFF) {
288 		l = (wc >> 8) & 0xFF;
289 		t = wc & 0xFF;
290 		if (ishangul(l, t) || isuda(l, t)) {
291 			*idx = (_index_t)wc;
292 			*csid = 1;
293 		} else {
294 			if (l >= 0xD9 && l <= 0xDE) {
295 				linear = l - 0xD9;
296 				m = 0x21;
297 			} else if (l >= 0xE0 && l <= 0xF9) {
298 				linear = l - 0xE0;
299 				m = 0x4A;
300 			} else {
301 				return EILSEQ;
302 			}
303 			linear *= 188;
304 			if (t >= 0x31 && t <= 0x7E) {
305 				linear += t - 0x31;
306 			} else if (t >= 0x91 && t <= 0xFE) {
307 				linear += t - 0x43;
308 			} else {
309 				return EILSEQ;
310 			}
311 			l = (linear / 94) + m;
312 			t = (linear % 94) + 0x21;
313 			*idx = (_index_t)((l << 8) | t);
314 			*csid = 2;
315 		}
316 	} else {
317 		return EILSEQ;
318 	}
319 	return 0;
320 }
321 
322 static __inline int
323 /*ARGSUSED*/
324 _citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei,
325 	wchar_t * __restrict wc, _csid_t csid, _index_t idx)
326 {
327 	int m, n, l, t, linear;
328 
329 	/* ei may be unused */
330 	_DIAGASSERT(wc != NULL);
331 
332 	switch (csid) {
333 	case 0:
334 	case 1:
335 		*wc = (wchar_t)idx;
336 		break;
337 	case 2:
338 		if (idx >= 0x2121 && idx <= 0x2C71) {
339 			m = 0xD9;
340 			n = 0x21;
341 		} else if (idx >= 0x4A21 && idx <= 0x7D7E) {
342 			m = 0xE0;
343 			n = 0x4A;
344 		} else {
345 			return EILSEQ;
346 		}
347 		l = ((idx >> 8) & 0xFF) - n;
348 		t = (idx & 0xFF) - 0x21;
349 		linear = (l * 94) + t;
350 		l = (linear / 188) + m;
351 		t = linear % 188;
352 		t += (t <= 0x4D) ? 0x31 : 0x43;
353 		break;
354 	default:
355 		return EILSEQ;
356 	}
357 	return 0;
358 }
359 
360 static __inline int
361 /*ARGSUSED*/
362 _citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei,
363 	_JOHABState * __restrict psenc, int * __restrict rstate)
364 {
365 	/* ei may be unused */
366 	_DIAGASSERT(psenc != NULL);
367 	_DIAGASSERT(rstate != NULL);
368 
369 	*rstate = (psenc->chlen == 0)
370 	    ? _STDENC_SDGEN_INITIAL
371 	    : _STDENC_SDGEN_INCOMPLETE_CHAR;
372 	return 0;
373 }
374 
375 /* ----------------------------------------------------------------------
376  * public interface for ctype
377  */
378 
379 _CITRUS_CTYPE_DECLS(JOHAB);
380 _CITRUS_CTYPE_DEF_OPS(JOHAB);
381 
382 #include "citrus_ctype_template.h"
383 
384 
385 /* ----------------------------------------------------------------------
386  * public interface for stdenc
387  */
388 
389 _CITRUS_STDENC_DECLS(JOHAB);
390 _CITRUS_STDENC_DEF_OPS(JOHAB);
391 
392 #include "citrus_stdenc_template.h"
393