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
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*/
_citrus_JOHAB_init_state(_JOHABEncodingInfo * __restrict ei __unused,_JOHABState * __restrict psenc)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*/
_citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo * ei __unused)106 _citrus_JOHAB_encoding_module_uninit(_JOHABEncodingInfo *ei __unused)
107 {
108
109 /* ei may be null */
110 }
111
112 static int
113 /*ARGSUSED*/
_citrus_JOHAB_encoding_module_init(_JOHABEncodingInfo * __restrict ei __unused,const void * __restrict var __unused,size_t lenvar __unused)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
ishangul(int l,int t)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
isuda(int l,int t)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
ishanja(int l,int t)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*/
_citrus_JOHAB_mbrtowc_priv(_JOHABEncodingInfo * __restrict ei,wchar_t * __restrict pwc,char ** __restrict s,size_t n,_JOHABState * __restrict psenc,size_t * __restrict nresult)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*/
_citrus_JOHAB_wcrtomb_priv(_JOHABEncodingInfo * __restrict ei __unused,char * __restrict s,size_t n,wchar_t wc,_JOHABState * __restrict psenc,size_t * __restrict nresult)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*/
_citrus_JOHAB_stdenc_wctocs(_JOHABEncodingInfo * __restrict ei __unused,_csid_t * __restrict csid,_index_t * __restrict idx,wchar_t wc)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*/
_citrus_JOHAB_stdenc_cstowc(_JOHABEncodingInfo * __restrict ei __unused,wchar_t * __restrict wc,_csid_t csid,_index_t idx)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*/
_citrus_JOHAB_stdenc_get_state_desc_generic(_JOHABEncodingInfo * __restrict ei __unused,_JOHABState * __restrict psenc,int * __restrict rstate)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