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