10db70a6aSJohn Marino /* $FreeBSD: head/lib/libiconv_modules/JOHAB/citrus_johab.c 281550 2015-04-15 09:09:20Z tijl $ */
20d5acd74SJohn Marino /* $NetBSD: citrus_johab.c,v 1.4 2008/06/14 16:01:07 tnozaki Exp $ */
30d5acd74SJohn Marino 
40d5acd74SJohn Marino /*-
50d5acd74SJohn Marino  * Copyright (c)2006 Citrus Project,
60d5acd74SJohn Marino  * All rights reserved.
70d5acd74SJohn Marino  *
80d5acd74SJohn Marino  * Redistribution and use in source and binary forms, with or without
90d5acd74SJohn Marino  * modification, are permitted provided that the following conditions
100d5acd74SJohn Marino  * are met:
110d5acd74SJohn Marino  * 1. Redistributions of source code must retain the above copyright
120d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer.
130d5acd74SJohn Marino  * 2. Redistributions in binary form must reproduce the above copyright
140d5acd74SJohn Marino  *    notice, this list of conditions and the following disclaimer in the
150d5acd74SJohn Marino  *    documentation and/or other materials provided with the distribution.
160d5acd74SJohn Marino  *
170d5acd74SJohn Marino  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
180d5acd74SJohn Marino  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
190d5acd74SJohn Marino  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
200d5acd74SJohn Marino  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
210d5acd74SJohn Marino  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
220d5acd74SJohn Marino  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
230d5acd74SJohn Marino  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
240d5acd74SJohn Marino  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
250d5acd74SJohn Marino  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
260d5acd74SJohn Marino  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
270d5acd74SJohn Marino  * SUCH DAMAGE.
280d5acd74SJohn Marino  */
290d5acd74SJohn Marino #include <sys/cdefs.h>
300d5acd74SJohn Marino #include <sys/types.h>
310d5acd74SJohn Marino 
320d5acd74SJohn Marino #include <assert.h>
330d5acd74SJohn Marino #include <errno.h>
340d5acd74SJohn Marino #include <limits.h>
350d5acd74SJohn Marino #include <stdbool.h>
360d5acd74SJohn Marino #include <stddef.h>
370d5acd74SJohn Marino #include <stdint.h>
380d5acd74SJohn Marino #include <stdio.h>
390d5acd74SJohn Marino #include <stdlib.h>
400d5acd74SJohn Marino #include <string.h>
410d5acd74SJohn Marino #include <wchar.h>
420d5acd74SJohn Marino 
430d5acd74SJohn Marino #include "citrus_namespace.h"
440d5acd74SJohn Marino #include "citrus_types.h"
450d5acd74SJohn Marino #include "citrus_bcs.h"
460d5acd74SJohn Marino #include "citrus_module.h"
470d5acd74SJohn Marino #include "citrus_stdenc.h"
480d5acd74SJohn Marino #include "citrus_johab.h"
490d5acd74SJohn Marino 
500d5acd74SJohn Marino /* ----------------------------------------------------------------------
510d5acd74SJohn Marino  * private stuffs used by templates
520d5acd74SJohn Marino  */
530d5acd74SJohn Marino 
540d5acd74SJohn Marino typedef struct {
550d5acd74SJohn Marino 	int	 chlen;
560d5acd74SJohn Marino 	char	 ch[2];
570d5acd74SJohn Marino } _JOHABState;
580d5acd74SJohn Marino 
590d5acd74SJohn Marino typedef struct {
600d5acd74SJohn Marino 	int	 dummy;
610d5acd74SJohn Marino } _JOHABEncodingInfo;
620d5acd74SJohn Marino 
630d5acd74SJohn Marino #define _CEI_TO_EI(_cei_)		(&(_cei_)->ei)
640d5acd74SJohn Marino #define _CEI_TO_STATE(_cei_, _func_)	(_cei_)->states.s_##_func_
650d5acd74SJohn Marino 
660d5acd74SJohn Marino #define _FUNCNAME(m)			_citrus_JOHAB_##m
670d5acd74SJohn Marino #define _ENCODING_INFO			_JOHABEncodingInfo
680d5acd74SJohn Marino #define _ENCODING_STATE			_JOHABState
690d5acd74SJohn Marino #define _ENCODING_MB_CUR_MAX(_ei_)		2
700d5acd74SJohn Marino #define _ENCODING_IS_STATE_DEPENDENT		0
710d5acd74SJohn Marino #define _STATE_NEEDS_EXPLICIT_INIT(_ps_)	0
720d5acd74SJohn Marino 
730d5acd74SJohn Marino 
740d5acd74SJohn Marino static __inline void
750d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused,_JOHABState * __restrict psenc)760d5acd74SJohn Marino _citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused,
770d5acd74SJohn Marino     _JOHABState * __restrict psenc)
780d5acd74SJohn Marino {
790d5acd74SJohn Marino 
800d5acd74SJohn Marino 	psenc->chlen = 0;
810d5acd74SJohn Marino }
820d5acd74SJohn Marino 
83*71ea2de5SJohn Marino #if 0
840d5acd74SJohn Marino static __inline void
850d5acd74SJohn Marino /*ARGSUSED*/
860d5acd74SJohn Marino _citrus_JOHAB_pack_state(_JOHABEncodingInfo * __restrict ei __unused,
870d5acd74SJohn Marino     void * __restrict pspriv, const _JOHABState * __restrict psenc)
880d5acd74SJohn Marino {
890d5acd74SJohn Marino 
900d5acd74SJohn Marino 	memcpy(pspriv, (const void *)psenc, sizeof(*psenc));
910d5acd74SJohn Marino }
920d5acd74SJohn Marino 
930d5acd74SJohn Marino static __inline void
940d5acd74SJohn Marino /*ARGSUSED*/
950d5acd74SJohn Marino _citrus_JOHAB_unpack_state(_JOHABEncodingInfo * __restrict ei __unused,
960d5acd74SJohn Marino     _JOHABState * __restrict psenc, const void * __restrict pspriv)
970d5acd74SJohn Marino {
980d5acd74SJohn Marino 
990d5acd74SJohn Marino 	memcpy((void *)psenc, pspriv, sizeof(*psenc));
1000d5acd74SJohn Marino }
101*71ea2de5SJohn Marino #endif
1020d5acd74SJohn Marino 
1030d5acd74SJohn Marino static void
1040d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo * ei __unused)1050d5acd74SJohn Marino _citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei __unused)
1060d5acd74SJohn Marino {
1070d5acd74SJohn Marino 
1080d5acd74SJohn Marino 	/* ei may be null */
1090d5acd74SJohn Marino }
1100d5acd74SJohn Marino 
1110d5acd74SJohn Marino static int
1120d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused,const void * __restrict var __unused,size_t lenvar __unused)1130d5acd74SJohn Marino _citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused,
1140d5acd74SJohn Marino     const void * __restrict var __unused, size_t lenvar __unused)
1150d5acd74SJohn Marino {
1160d5acd74SJohn Marino 
1170d5acd74SJohn Marino 	/* ei may be null */
1180d5acd74SJohn Marino 	return (0);
1190d5acd74SJohn Marino }
1200d5acd74SJohn Marino 
1210d5acd74SJohn Marino static __inline bool
ishangul(int l,int t)1220d5acd74SJohn Marino ishangul(int l, int t)
1230d5acd74SJohn Marino {
1240d5acd74SJohn Marino 
1250d5acd74SJohn Marino 	return ((l >= 0x84 && l <= 0xD3) &&
1260d5acd74SJohn Marino 	    ((t >= 0x41 && t <= 0x7E) || (t >= 0x81 && t <= 0xFE)));
1270d5acd74SJohn Marino }
1280d5acd74SJohn Marino 
1290d5acd74SJohn Marino static __inline bool
isuda(int l,int t)1300d5acd74SJohn Marino isuda(int l, int t)
1310d5acd74SJohn Marino {
1320d5acd74SJohn Marino 
1330d5acd74SJohn Marino 	return ((l == 0xD8) &&
1340d5acd74SJohn Marino 	    ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
1350d5acd74SJohn Marino }
1360d5acd74SJohn Marino 
1370d5acd74SJohn Marino static __inline bool
ishanja(int l,int t)1380d5acd74SJohn Marino ishanja(int l, int t)
1390d5acd74SJohn Marino {
1400d5acd74SJohn Marino 
1410d5acd74SJohn Marino 	return (((l >= 0xD9 && l <= 0xDE) || (l >= 0xE0 && l <= 0xF9)) &&
1420d5acd74SJohn Marino 	    ((t >= 0x31 && t <= 0x7E) || (t >= 0x91 && t <= 0xFE)));
1430d5acd74SJohn Marino }
1440d5acd74SJohn Marino 
1450d5acd74SJohn Marino static int
1460d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,wchar_t * __restrict pwc,char ** __restrict s,size_t n,_JOHABState * __restrict psenc,size_t * __restrict nresult)1470d5acd74SJohn Marino _citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,
1480db70a6aSJohn Marino     wchar_t * __restrict pwc, char ** __restrict s, size_t n,
1490d5acd74SJohn Marino     _JOHABState * __restrict psenc, size_t * __restrict nresult)
1500d5acd74SJohn Marino {
1510db70a6aSJohn Marino 	char *s0;
1520d5acd74SJohn Marino 	int l, t;
1530d5acd74SJohn Marino 
1540d5acd74SJohn Marino 	if (*s == NULL) {
1550d5acd74SJohn Marino 		_citrus_JOHAB_init_state(ei, psenc);
1560d5acd74SJohn Marino 		*nresult = _ENCODING_IS_STATE_DEPENDENT;
1570d5acd74SJohn Marino 		return (0);
1580d5acd74SJohn Marino 	}
1590d5acd74SJohn Marino 	s0 = *s;
1600d5acd74SJohn Marino 
1610d5acd74SJohn Marino 	switch (psenc->chlen) {
1620d5acd74SJohn Marino 	case 0:
1630d5acd74SJohn Marino 		if (n-- < 1)
1640d5acd74SJohn Marino 			goto restart;
1650d5acd74SJohn Marino 		l = *s0++ & 0xFF;
1660d5acd74SJohn Marino 		if (l <= 0x7F) {
1670d5acd74SJohn Marino 			if (pwc != NULL)
1680d5acd74SJohn Marino 				*pwc = (wchar_t)l;
1690d5acd74SJohn Marino 			*nresult = (l == 0) ? 0 : 1;
1700d5acd74SJohn Marino 			*s = s0;
1710d5acd74SJohn Marino 			return (0);
1720d5acd74SJohn Marino 		}
1730d5acd74SJohn Marino 		psenc->ch[psenc->chlen++] = l;
1740d5acd74SJohn Marino 		break;
1750d5acd74SJohn Marino 	case 1:
1760d5acd74SJohn Marino 		l = psenc->ch[0] & 0xFF;
1770d5acd74SJohn Marino 		break;
1780d5acd74SJohn Marino 	default:
1790d5acd74SJohn Marino 		return (EINVAL);
1800d5acd74SJohn Marino 	}
1810d5acd74SJohn Marino 	if (n-- < 1) {
1820d5acd74SJohn Marino restart:
1830d5acd74SJohn Marino 		*nresult = (size_t)-2;
1840d5acd74SJohn Marino 		*s = s0;
1850d5acd74SJohn Marino 		return (0);
1860d5acd74SJohn Marino 	}
1870d5acd74SJohn Marino 	t = *s0++ & 0xFF;
1880d5acd74SJohn Marino 	if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t)) {
1890d5acd74SJohn Marino 		*nresult = (size_t)-1;
1900d5acd74SJohn Marino 		return (EILSEQ);
1910d5acd74SJohn Marino 	}
1920d5acd74SJohn Marino 	if (pwc != NULL)
1930d5acd74SJohn Marino 		*pwc = (wchar_t)(l << 8 | t);
1940d5acd74SJohn Marino 	*nresult = s0 - *s;
1950d5acd74SJohn Marino 	*s = s0;
1960d5acd74SJohn Marino 	psenc->chlen = 0;
1970d5acd74SJohn Marino 
1980d5acd74SJohn Marino 	return (0);
1990d5acd74SJohn Marino }
2000d5acd74SJohn Marino 
2010d5acd74SJohn Marino static int
2020d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused,char * __restrict s,size_t n,wchar_t wc,_JOHABState * __restrict psenc,size_t * __restrict nresult)2030d5acd74SJohn Marino _citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused,
2040d5acd74SJohn Marino     char * __restrict s, size_t n, wchar_t wc,
2050d5acd74SJohn Marino     _JOHABState * __restrict psenc, size_t * __restrict nresult)
2060d5acd74SJohn Marino {
2070d5acd74SJohn Marino 	int l, t;
2080d5acd74SJohn Marino 
2090d5acd74SJohn Marino 	if (psenc->chlen != 0)
2100d5acd74SJohn Marino 		return (EINVAL);
2110d5acd74SJohn Marino 
2120d5acd74SJohn Marino 	/* XXX assume wchar_t as int */
2130d5acd74SJohn Marino 	if ((uint32_t)wc <= 0x7F) {
2140d5acd74SJohn Marino 		if (n < 1)
2150d5acd74SJohn Marino 			goto e2big;
2160d5acd74SJohn Marino 		*s = wc & 0xFF;
2170d5acd74SJohn Marino 		*nresult = 1;
2180d5acd74SJohn Marino 	} else if ((uint32_t)wc <= 0xFFFF) {
2190d5acd74SJohn Marino 		if (n < 2) {
2200d5acd74SJohn Marino e2big:
2210d5acd74SJohn Marino 			*nresult = (size_t)-1;
2220d5acd74SJohn Marino 			return (E2BIG);
2230d5acd74SJohn Marino 		}
2240d5acd74SJohn Marino 		l = (wc >> 8) & 0xFF;
2250d5acd74SJohn Marino 		t = wc & 0xFF;
2260d5acd74SJohn Marino 		if (!ishangul(l, t) && !isuda(l, t) && !ishanja(l, t))
2270d5acd74SJohn Marino 			goto ilseq;
2280d5acd74SJohn Marino 		*s++ = l;
2290d5acd74SJohn Marino 		*s = t;
2300d5acd74SJohn Marino 		*nresult = 2;
2310d5acd74SJohn Marino 	} else {
2320d5acd74SJohn Marino ilseq:
2330d5acd74SJohn Marino 		*nresult = (size_t)-1;
2340d5acd74SJohn Marino 		return (EILSEQ);
2350d5acd74SJohn Marino 	}
2360d5acd74SJohn Marino 	return (0);
2370d5acd74SJohn Marino 
2380d5acd74SJohn Marino }
2390d5acd74SJohn Marino 
2400d5acd74SJohn Marino static __inline int
2410d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)2420d5acd74SJohn Marino _citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused,
2430d5acd74SJohn Marino     _csid_t * __restrict csid, _index_t * __restrict idx, wchar_t wc)
2440d5acd74SJohn Marino {
2450d5acd74SJohn Marino 	int m, l, linear, t;
2460d5acd74SJohn Marino 
2470d5acd74SJohn Marino 	/* XXX assume wchar_t as int */
2480d5acd74SJohn Marino 	if ((uint32_t)wc <= 0x7F) {
2490d5acd74SJohn Marino 		*idx = (_index_t)wc;
2500d5acd74SJohn Marino 		*csid = 0;
2510d5acd74SJohn Marino 	} else if ((uint32_t)wc <= 0xFFFF) {
2520d5acd74SJohn Marino 		l = (wc >> 8) & 0xFF;
2530d5acd74SJohn Marino 		t = wc & 0xFF;
2540d5acd74SJohn Marino 		if (ishangul(l, t) || isuda(l, t)) {
2550d5acd74SJohn Marino 			*idx = (_index_t)wc;
2560d5acd74SJohn Marino 			*csid = 1;
2570d5acd74SJohn Marino 		} else {
2580d5acd74SJohn Marino 			if (l >= 0xD9 && l <= 0xDE) {
2590d5acd74SJohn Marino 				linear = l - 0xD9;
2600d5acd74SJohn Marino 				m = 0x21;
2610d5acd74SJohn Marino 			} else if (l >= 0xE0 && l <= 0xF9) {
2620d5acd74SJohn Marino 				linear = l - 0xE0;
2630d5acd74SJohn Marino 				m = 0x4A;
2640d5acd74SJohn Marino 			} else
2650d5acd74SJohn Marino 				return (EILSEQ);
2660d5acd74SJohn Marino 			linear *= 188;
2670d5acd74SJohn Marino 			if (t >= 0x31 && t <= 0x7E)
2680d5acd74SJohn Marino 				linear += t - 0x31;
2690d5acd74SJohn Marino 			else if (t >= 0x91 && t <= 0xFE)
2700d5acd74SJohn Marino 				linear += t - 0x43;
2710d5acd74SJohn Marino 			else
2720d5acd74SJohn Marino 				return (EILSEQ);
2730d5acd74SJohn Marino 			l = (linear / 94) + m;
2740d5acd74SJohn Marino 			t = (linear % 94) + 0x21;
2750d5acd74SJohn Marino 			*idx = (_index_t)((l << 8) | t);
2760d5acd74SJohn Marino 			*csid = 2;
2770d5acd74SJohn Marino 		}
2780d5acd74SJohn Marino 	} else
2790d5acd74SJohn Marino 		return (EILSEQ);
2800d5acd74SJohn Marino 	return (0);
2810d5acd74SJohn Marino }
2820d5acd74SJohn Marino 
2830d5acd74SJohn Marino static __inline int
2840d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused,wchar_t * __restrict wc,_csid_t csid,_index_t idx)2850d5acd74SJohn Marino _citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused,
2860d5acd74SJohn Marino     wchar_t * __restrict wc, _csid_t csid, _index_t idx)
2870d5acd74SJohn Marino {
2880d5acd74SJohn Marino 	int m, n, l, linear, t;
2890d5acd74SJohn Marino 
2900d5acd74SJohn Marino 	switch (csid) {
2910d5acd74SJohn Marino 	case 0:
2920d5acd74SJohn Marino 	case 1:
2930d5acd74SJohn Marino 		*wc = (wchar_t)idx;
2940d5acd74SJohn Marino 		break;
2950d5acd74SJohn Marino 	case 2:
2960d5acd74SJohn Marino 		if (idx >= 0x2121 && idx <= 0x2C71) {
2970d5acd74SJohn Marino 			m = 0xD9;
2980d5acd74SJohn Marino 			n = 0x21;
2990d5acd74SJohn Marino 		} else if (idx >= 0x4A21 && idx <= 0x7D7E) {
3000d5acd74SJohn Marino 			m = 0xE0;
3010d5acd74SJohn Marino 			n = 0x4A;
3020d5acd74SJohn Marino 		} else
3030d5acd74SJohn Marino 			return (EILSEQ);
3040d5acd74SJohn Marino 		l = ((idx >> 8) & 0xFF) - n;
3050d5acd74SJohn Marino 		t = (idx & 0xFF) - 0x21;
3060d5acd74SJohn Marino 		linear = (l * 94) + t;
3070d5acd74SJohn Marino 		l = (linear / 188) + m;
3080d5acd74SJohn Marino 		t = linear % 188;
3090d5acd74SJohn Marino 		t += (t <= 0x4D) ? 0x31 : 0x43;
3100d5acd74SJohn Marino 		break;
3110d5acd74SJohn Marino 	default:
3120d5acd74SJohn Marino 		return (EILSEQ);
3130d5acd74SJohn Marino 	}
3140d5acd74SJohn Marino 	return (0);
3150d5acd74SJohn Marino }
3160d5acd74SJohn Marino 
3170d5acd74SJohn Marino static __inline int
3180d5acd74SJohn Marino /*ARGSUSED*/
_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused,_JOHABState * __restrict psenc,int * __restrict rstate)3190d5acd74SJohn Marino _citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused,
3200d5acd74SJohn Marino     _JOHABState * __restrict psenc, int * __restrict rstate)
3210d5acd74SJohn Marino {
3220d5acd74SJohn Marino 
3230d5acd74SJohn Marino 	*rstate = (psenc->chlen == 0) ? _STDENC_SDGEN_INITIAL :
3240d5acd74SJohn Marino 	    _STDENC_SDGEN_INCOMPLETE_CHAR;
3250d5acd74SJohn Marino 	return (0);
3260d5acd74SJohn Marino }
3270d5acd74SJohn Marino 
3280d5acd74SJohn Marino /* ----------------------------------------------------------------------
3290d5acd74SJohn Marino  * public interface for stdenc
3300d5acd74SJohn Marino  */
3310d5acd74SJohn Marino 
3320d5acd74SJohn Marino _CITRUS_STDENC_DECLS(JOHAB);
3330d5acd74SJohn Marino _CITRUS_STDENC_DEF_OPS(JOHAB);
3340d5acd74SJohn Marino 
3350d5acd74SJohn Marino #include "citrus_stdenc_template.h"
336