xref: /netbsd/lib/libc/citrus/modules/citrus_johab.c (revision 0192bd2d)
1 /* $NetBSD: citrus_johab.c,v 1.7 2019/07/08 06:45:01 mlelstv 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.7 2019/07/08 06:45:01 mlelstv 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_mbsnrtowcs;
75 		_JOHABState	s_wcrtomb;
76 		_JOHABState	s_wcsrtombs;
77 		_JOHABState	s_wcsnrtombs;
78 		_JOHABState	s_wctomb;
79 	} states;
80 } _JOHABCTypeInfo;
81 
82 #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
83 #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
84 
85 #define _FUNCNAME(m)			_citrus_JOHAB_##m
86 #define _ENCODING_INFO			_JOHABEncodingInfo
87 #define _CTYPE_INFO			_JOHABCTypeInfo
88 #define _ENCODING_STATE			_JOHABState
89 #define _ENCODING_MB_CUR_MAX(_ei_)		2
90 #define _ENCODING_IS_STATE_DEPENDENT		0
91 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
92 
93 
94 static __inline void
95 /*ARGSUSED*/
_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei,_JOHABState * __restrict psenc)96 _citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei,
97 	_JOHABState * __restrict psenc)
98 {
99 	/* ei may be null */
100 	_DIAGASSERT(psenc != NULL);
101 
102 	psenc->chlen = 0;
103 }
104 
105 static __inline void
106 /*ARGSUSED*/
_citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei,void * __restrict pspriv,const _JOHABState * __restrict psenc)107 _citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei,
108 	void * __restrict pspriv,
109 	const _JOHABState * __restrict psenc)
110 {
111 	/* ei may be null */
112 	_DIAGASSERT(pspriv != NULL);
113 	_DIAGASSERT(psenc != NULL);
114 
115 	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
116 }
117 
118 static __inline void
119 /*ARGSUSED*/
_citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei,_JOHABState * __restrict psenc,const void * __restrict pspriv)120 _citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei,
121 	_JOHABState * __restrict psenc,
122 	const void * __restrict pspriv)
123 {
124 	/* ei may be null */
125 	_DIAGASSERT(psenc != NULL);
126 	_DIAGASSERT(pspriv != NULL);
127 
128 	memcpy((void *)psenc, pspriv, sizeof(*psenc));
129 }
130 
131 static void
132 /*ARGSUSED*/
_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo * ei)133 _citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei)
134 {
135 	/* ei may be null */
136 }
137 
138 static int
139 /*ARGSUSED*/
_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei,const void * __restrict var,size_t lenvar)140 _citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei,
141 	const void * __restrict var, size_t lenvar)
142 {
143 	/* ei may be null */
144 	return 0;
145 }
146 
147 static __inline int
ishangul(int l,int t)148 ishangul(int l, int t)
149 {
150 
151 	return (l >= 0x84 && l <= 0xD3) &&
152 	      ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE));
153 }
154 
155 static __inline int
isuda(int l,int t)156 isuda(int l, int t)
157 {
158 	return (l == 0xD8) &&
159 	       ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE));
160 }
161 
162 static __inline int
ishanja(int l,int t)163 ishanja(int l, int t)
164 {
165 	return ((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
166 	       ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE));
167 }
168 
169 static int
170 /*ARGSUSED*/
_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,wchar_t * __restrict pwc,const char ** __restrict s,size_t n,_JOHABState * __restrict psenc,size_t * __restrict nresult)171 _citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
172 	wchar_t * __restrict pwc, const char ** __restrict s, size_t n,
173 	_JOHABState * __restrict psenc, size_t * __restrict nresult)
174 {
175 	const char *s0;
176 	int l, t;
177 
178 	/* ei may be unused */
179 	_DIAGASSERT(s != NULL);
180 	_DIAGASSERT(psenc != NULL);
181 	_DIAGASSERT(nresult != 0);
182 
183 	if (*s == NULL) {
184 		_citrus_JOHAB_init_state(ei, psenc);
185 		*nresult = _ENCODING_IS_STATE_DEPENDENT;
186 		return 0;
187 	}
188 	s0 = *s;
189 
190 	switch (psenc->chlen) {
191 	case 0:
192 		if (n-- < 1)
193 			goto restart;
194 		l = *s0++ & 0xFF;
195 		if (l <= 0x7F) {
196 			if (pwc != NULL)
197 				*pwc = (wchar_t)l;
198 			*nresult = (l == 0) ? 0 : 1;
199 			*s = s0;
200 			return 0;
201 		}
202 		psenc->ch[psenc->chlen++] = l;
203 		break;
204 	case 1:
205 		l = psenc->ch[0] & 0xFF;
206 		break;
207 	default:
208 		return EINVAL;
209 	}
210 	if (n-- < 1) {
211 restart:
212 		*nresult = (size_t)-2;
213 		*s = s0;
214 		return 0;
215 	}
216 	t = *s0++ & 0xFF;
217 	if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
218 		*nresult = (size_t)-1;
219 		return EILSEQ;
220 	}
221 	if (pwc != NULL)
222 		*pwc = (wchar_t)(l << 8 | t);
223 	*nresult = s0 - *s;
224 	*s = s0;
225 	psenc->chlen = 0;
226 
227 	return 0;
228 }
229 
230 static int
231 /*ARGSUSED*/
_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei,char * __restrict s,size_t n,wchar_t wc,_JOHABState * __restrict psenc,size_t * __restrict nresult)232 _citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei,
233 	char * __restrict s, size_t n, wchar_t wc,
234 	_JOHABState * __restrict psenc, size_t * __restrict nresult)
235 {
236 	int l, t;
237 
238 	/* ei may be unused */
239 	_DIAGASSERT(s != NULL);
240 	_DIAGASSERT(psenc != NULL);
241 	_DIAGASSERT(nresult != NULL);
242 
243 	if (psenc->chlen != 0)
244 		return EINVAL;
245 
246 	/* XXX assume wchar_t as int */
247 	if ((uint32_t)wc <= 0x7F) {
248 		if (n < 1)
249 			goto e2big;
250 		*s = wc & 0xFF;
251 		*nresult = 1;
252 	} else if ((uint32_t)wc <= 0xFFFF) {
253 		if (n < 2) {
254 e2big:
255 			*nresult = (size_t)-1;
256 			return E2BIG;
257 		}
258 		l = (wc >> 8) & 0xFF;
259 		t = wc & 0xFF;
260 		if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
261 			goto ilseq;
262 		*s++ = l;
263 		*s = t;
264 		*nresult = 2;
265 	} else {
266 ilseq:
267 		*nresult = (size_t)-1;
268 		return EILSEQ;
269 	}
270 	return 0;
271 
272 }
273 
274 static __inline int
275 /*ARGSUSED*/
_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)276 _citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei,
277 	_csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
278 {
279 	int m, l, t, linear;
280 
281 	/* ei may be unused */
282 	_DIAGASSERT(csid != NULL);
283 	_DIAGASSERT(idx != NULL);
284 
285 	/* XXX assume wchar_t as int */
286 	if ((uint32_t)wc <= 0x7F) {
287 		*idx = (_index_t)wc;
288 		*csid = 0;
289 	} else if ((uint32_t)wc <= 0xFFFF) {
290 		l = (wc >> 8) & 0xFF;
291 		t = wc & 0xFF;
292 		if (ishangul(l, t) || isuda(l, t)) {
293 			*idx = (_index_t)wc;
294 			*csid = 1;
295 		} else {
296 			if (l >= 0xD9 && l <= 0xDE) {
297 				linear = l - 0xD9;
298 				m = 0x21;
299 			} else if (l >= 0xE0 && l <= 0xF9) {
300 				linear = l - 0xE0;
301 				m = 0x4A;
302 			} else {
303 				return EILSEQ;
304 			}
305 			linear *= 188;
306 			if (t >= 0x31 && t <= 0x7E) {
307 				linear += t - 0x31;
308 			} else if (t >= 0x91 && t <= 0xFE) {
309 				linear += t - 0x43;
310 			} else {
311 				return EILSEQ;
312 			}
313 			l = (linear / 94) + m;
314 			t = (linear % 94) + 0x21;
315 			*idx = (_index_t)((l << 8) | t);
316 			*csid = 2;
317 		}
318 	} else {
319 		return EILSEQ;
320 	}
321 	return 0;
322 }
323 
324 static __inline int
325 /*ARGSUSED*/
_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei,wchar_t * __restrict wc,_csid_t csid,_index_t idx)326 _citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei,
327 	wchar_t * __restrict wc, _csid_t csid, _index_t idx)
328 {
329 	int m, n, l, t, linear;
330 
331 	/* ei may be unused */
332 	_DIAGASSERT(wc != NULL);
333 
334 	switch (csid) {
335 	case 0:
336 	case 1:
337 		*wc = (wchar_t)idx;
338 		break;
339 	case 2:
340 		if (idx >= 0x2121 && idx <= 0x2C71) {
341 			m = 0xD9;
342 			n = 0x21;
343 		} else if (idx >= 0x4A21 && idx <= 0x7D7E) {
344 			m = 0xE0;
345 			n = 0x4A;
346 		} else {
347 			return EILSEQ;
348 		}
349 		l = ((idx >> 8) & 0xFF) - n;
350 		t = (idx & 0xFF) - 0x21;
351 		linear = (l * 94) + t;
352 		l = (linear / 188) + m;
353 		t = linear % 188;
354 		t += (t <= 0x4D) ? 0x31 : 0x43;
355 		*wc = (wchar_t)((l << 8) | t);
356 		break;
357 	default:
358 		return EILSEQ;
359 	}
360 	return 0;
361 }
362 
363 static __inline int
364 /*ARGSUSED*/
_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei,_JOHABState * __restrict psenc,int * __restrict rstate)365 _citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei,
366 	_JOHABState * __restrict psenc, int * __restrict rstate)
367 {
368 	/* ei may be unused */
369 	_DIAGASSERT(psenc != NULL);
370 	_DIAGASSERT(rstate != NULL);
371 
372 	*rstate = (psenc->chlen == 0)
373 	    ? _STDENC_SDGEN_INITIAL
374 	    : _STDENC_SDGEN_INCOMPLETE_CHAR;
375 	return 0;
376 }
377 
378 /* ----------------------------------------------------------------------
379  * public interface for ctype
380  */
381 
382 _CITRUS_CTYPE_DECLS(JOHAB);
383 _CITRUS_CTYPE_DEF_OPS(JOHAB);
384 
385 #include "citrus_ctype_template.h"
386 
387 
388 /* ----------------------------------------------------------------------
389  * public interface for stdenc
390  */
391 
392 _CITRUS_STDENC_DECLS(JOHAB);
393 _CITRUS_STDENC_DEF_OPS(JOHAB);
394 
395 #include "citrus_stdenc_template.h"
396