1 /* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $ */
2 
3 /*-
4  * SPDX-License-Identifier: BSD-2-Clause
5  *
6  * Copyright (c)2006 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 #include <sys/cdefs.h>
31 #include <sys/types.h>
32 
33 #include <assert.h>
34 #include <errno.h>
35 #include <limits.h>
36 #include <stdbool.h>
37 #include <stddef.h>
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <wchar.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_stdenc.h"
49 #include "citrus_johab.h"
50 
51 /* ----------------------------------------------------------------------
52  * private stuffs used by templates
53  */
54 
55 typedef struct {
56 	int	 chlen;
57 	char	 ch[2];
58 } _JOHABState;
59 
60 typedef struct {
61 	int	 dummy;
62 } _JOHABEncodingInfo;
63 
64 #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
65 #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
66 
67 #define _FUNCNAME(m)			_citrus_JOHAB_##m
68 #define _ENCODING_INFO			_JOHABEncodingInfo
69 #define _ENCODING_STATE			_JOHABState
70 #define _ENCODING_MB_CUR_MAX(_ei_)		2
71 #define _ENCODING_IS_STATE_DEPENDENT		0
72 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
73 
74 
75 static __inline void
76 /*ARGSUSED*/
77 _citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused,
78     _JOHABState * __restrict psenc)
79 {
80 
81 	psenc->chlen = 0;
82 }
83 
84 #if 0
85 static __inline void
86 /*ARGSUSED*/
87 _citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei __unused,
88     void * __restrict pspriv, const _JOHABState * __restrict psenc)
89 {
90 
91 	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
92 }
93 
94 static __inline void
95 /*ARGSUSED*/
96 _citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei __unused,
97     _JOHABState * __restrict psenc, const void * __restrict pspriv)
98 {
99 
100 	memcpy((void *)psenc, pspriv, sizeof(*psenc));
101 }
102 #endif
103 
104 static void
105 /*ARGSUSED*/
106 _citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei __unused)
107 {
108 
109 	/* ei may be null */
110 }
111 
112 static int
113 /*ARGSUSED*/
114 _citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused,
115     const void * __restrict var __unused, size_t lenvar __unused)
116 {
117 
118 	/* ei may be null */
119 	return (0);
120 }
121 
122 static __inline bool
123 ishangul(int l, int t)
124 {
125 
126 	return ((l >= 0x84 && l <= 0xD3) &&
127 	    ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE)));
128 }
129 
130 static __inline bool
131 isuda(int l, int t)
132 {
133 
134 	return ((l == 0xD8) &&
135 	    ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
136 }
137 
138 static __inline bool
139 ishanja(int l, int t)
140 {
141 
142 	return (((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
143 	    ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
144 }
145 
146 static int
147 /*ARGSUSED*/
148 _citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
149     wchar_t * __restrict pwc, char ** __restrict s, size_t n,
150     _JOHABState * __restrict psenc, size_t * __restrict nresult)
151 {
152 	char *s0;
153 	int l, t;
154 
155 	if (*s == NULL) {
156 		_citrus_JOHAB_init_state(ei, psenc);
157 		*nresult = _ENCODING_IS_STATE_DEPENDENT;
158 		return (0);
159 	}
160 	s0 = *s;
161 
162 	switch (psenc->chlen) {
163 	case 0:
164 		if (n-- < 1)
165 			goto restart;
166 		l = *s0++ & 0xFF;
167 		if (l <= 0x7F) {
168 			if (pwc != NULL)
169 				*pwc = (wchar_t)l;
170 			*nresult = (l == 0) ? 0 : 1;
171 			*s = s0;
172 			return (0);
173 		}
174 		psenc->ch[psenc->chlen++] = l;
175 		break;
176 	case 1:
177 		l = psenc->ch[0] & 0xFF;
178 		break;
179 	default:
180 		return (EINVAL);
181 	}
182 	if (n-- < 1) {
183 restart:
184 		*nresult = (size_t)-2;
185 		*s = s0;
186 		return (0);
187 	}
188 	t = *s0++ & 0xFF;
189 	if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
190 		*nresult = (size_t)-1;
191 		return (EILSEQ);
192 	}
193 	if (pwc != NULL)
194 		*pwc = (wchar_t)(l << 8 | t);
195 	*nresult = s0 - *s;
196 	*s = s0;
197 	psenc->chlen = 0;
198 
199 	return (0);
200 }
201 
202 static int
203 /*ARGSUSED*/
204 _citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused,
205     char * __restrict s, size_t n, wchar_t wc,
206     _JOHABState * __restrict psenc, size_t * __restrict nresult)
207 {
208 	int l, t;
209 
210 	if (psenc->chlen != 0)
211 		return (EINVAL);
212 
213 	/* XXX assume wchar_t as int */
214 	if ((uint32_t)wc <= 0x7F) {
215 		if (n < 1)
216 			goto e2big;
217 		*s = wc & 0xFF;
218 		*nresult = 1;
219 	} else if ((uint32_t)wc <= 0xFFFF) {
220 		if (n < 2) {
221 e2big:
222 			*nresult = (size_t)-1;
223 			return (E2BIG);
224 		}
225 		l = (wc >> 8) & 0xFF;
226 		t = wc & 0xFF;
227 		if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
228 			goto ilseq;
229 		*s++ = l;
230 		*s = t;
231 		*nresult = 2;
232 	} else {
233 ilseq:
234 		*nresult = (size_t)-1;
235 		return (EILSEQ);
236 	}
237 	return (0);
238 
239 }
240 
241 static __inline int
242 /*ARGSUSED*/
243 _citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused,
244     _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
245 {
246 	int m, l, linear, t;
247 
248 	/* XXX assume wchar_t as int */
249 	if ((uint32_t)wc <= 0x7F) {
250 		*idx = (_index_t)wc;
251 		*csid = 0;
252 	} else if ((uint32_t)wc <= 0xFFFF) {
253 		l = (wc >> 8) & 0xFF;
254 		t = wc & 0xFF;
255 		if (ishangul(l, t) || isuda(l, t)) {
256 			*idx = (_index_t)wc;
257 			*csid = 1;
258 		} else {
259 			if (l >= 0xD9 && l <= 0xDE) {
260 				linear = l - 0xD9;
261 				m = 0x21;
262 			} else if (l >= 0xE0 && l <= 0xF9) {
263 				linear = l - 0xE0;
264 				m = 0x4A;
265 			} else
266 				return (EILSEQ);
267 			linear *= 188;
268 			if (t >= 0x31 && t <= 0x7E)
269 				linear += t - 0x31;
270 			else if (t >= 0x91 && t <= 0xFE)
271 				linear += t - 0x43;
272 			else
273 				return (EILSEQ);
274 			l = (linear / 94) + m;
275 			t = (linear % 94) + 0x21;
276 			*idx = (_index_t)((l << 8) | t);
277 			*csid = 2;
278 		}
279 	} else
280 		return (EILSEQ);
281 	return (0);
282 }
283 
284 static __inline int
285 /*ARGSUSED*/
286 _citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused,
287     wchar_t * __restrict wc, _csid_t csid, _index_t idx)
288 {
289 	int m, n, l, linear, t;
290 
291 	switch (csid) {
292 	case 0:
293 	case 1:
294 		*wc = (wchar_t)idx;
295 		break;
296 	case 2:
297 		if (idx >= 0x2121 && idx <= 0x2C71) {
298 			m = 0xD9;
299 			n = 0x21;
300 		} else if (idx >= 0x4A21 && idx <= 0x7D7E) {
301 			m = 0xE0;
302 			n = 0x4A;
303 		} else
304 			return (EILSEQ);
305 		l = ((idx >> 8) & 0xFF) - n;
306 		t = (idx & 0xFF) - 0x21;
307 		linear = (l * 94) + t;
308 		l = (linear / 188) + m;
309 		t = linear % 188;
310 		t += (t <= 0x4D) ? 0x31 : 0x43;
311 		break;
312 	default:
313 		return (EILSEQ);
314 	}
315 	return (0);
316 }
317 
318 static __inline int
319 /*ARGSUSED*/
320 _citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused,
321     _JOHABState * __restrict psenc, int * __restrict rstate)
322 {
323 
324 	*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
325 	    _STDENC_SDGEN_INCOMPLETE_CHAR;
326 	return (0);
327 }
328 
329 /* ----------------------------------------------------------------------
330  * public interface for stdenc
331  */
332 
333 _CITRUS_STDENC_DECLS(JOHAB);
334 _CITRUS_STDENC_DEF_OPS(JOHAB);
335 
336 #include "citrus_stdenc_template.h"
337