1 /* $NetBSD: citrus_big5.c,v 1.6 2003/06/25 09:51:41 tshiozak Exp $ */ 2 3 /*- 4 * Copyright (c)2002 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 29 /*- 30 * Copyright (c) 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * This code is derived from software contributed to Berkeley by 34 * Paul Borman at Krystal Technologies. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 3. All advertising materials mentioning features or use of this software 45 * must display the following acknowledgement: 46 * This product includes software developed by the University of 47 * California, Berkeley and its contributors. 48 * 4. Neither the name of the University nor the names of its contributors 49 * may be used to endorse or promote products derived from this software 50 * without specific prior written permission. 51 * 52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 62 * SUCH DAMAGE. 63 */ 64 65 #include <sys/cdefs.h> 66 #if defined(LIBC_SCCS) && !defined(lint) 67 __RCSID("$NetBSD: citrus_big5.c,v 1.6 2003/06/25 09:51:41 tshiozak Exp $"); 68 #endif /* LIBC_SCCS and not lint */ 69 70 #include <assert.h> 71 #include <errno.h> 72 #include <string.h> 73 #include <stdio.h> 74 #include <stdlib.h> 75 #include <stddef.h> 76 #include <locale.h> 77 #include <wchar.h> 78 #include <sys/types.h> 79 #include <limits.h> 80 81 #include "citrus_namespace.h" 82 #include "citrus_types.h" 83 #include "citrus_module.h" 84 #include "citrus_ctype.h" 85 #include "citrus_stdenc.h" 86 #include "citrus_big5.h" 87 88 /* ---------------------------------------------------------------------- 89 * private stuffs used by templates 90 */ 91 92 typedef struct { 93 char ch[2]; 94 int chlen; 95 } _BIG5State; 96 97 typedef struct { 98 int dummy; 99 } _BIG5EncodingInfo; 100 101 typedef struct { 102 _BIG5EncodingInfo ei; 103 struct { 104 /* for future multi-locale facility */ 105 _BIG5State s_mblen; 106 _BIG5State s_mbrlen; 107 _BIG5State s_mbrtowc; 108 _BIG5State s_mbtowc; 109 _BIG5State s_mbsrtowcs; 110 _BIG5State s_wcrtomb; 111 _BIG5State s_wcsrtombs; 112 _BIG5State s_wctomb; 113 } states; 114 } _BIG5CTypeInfo; 115 116 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei) 117 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ 118 119 #define _FUNCNAME(m) _citrus_BIG5_##m 120 #define _ENCODING_INFO _BIG5EncodingInfo 121 #define _CTYPE_INFO _BIG5CTypeInfo 122 #define _ENCODING_STATE _BIG5State 123 #define _ENCODING_MB_CUR_MAX(_ei_) 2 124 #define _ENCODING_IS_STATE_DEPENDENT 0 125 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 126 127 128 static __inline void 129 /*ARGSUSED*/ 130 _citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei, 131 _BIG5State * __restrict s) 132 { 133 memset(s, 0, sizeof(*s)); 134 } 135 136 static __inline void 137 /*ARGSUSED*/ 138 _citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei, 139 void * __restrict pspriv, 140 const _BIG5State * __restrict s) 141 { 142 memcpy(pspriv, (const void *)s, sizeof(*s)); 143 } 144 145 static __inline void 146 /*ARGSUSED*/ 147 _citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei, 148 _BIG5State * __restrict s, 149 const void * __restrict pspriv) 150 { 151 memcpy((void *)s, pspriv, sizeof(*s)); 152 } 153 154 static __inline int 155 _citrus_BIG5_check(u_int c) 156 { 157 c &= 0xff; 158 return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1); 159 } 160 161 static __inline int 162 _citrus_BIG5_check2(u_int c) 163 { 164 c &= 0xff; 165 if ((c >= 0x40 && c <= 0x7f) || (c >= 0xa1 && c <= 0xfe)) 166 return 1; 167 else 168 return 0; 169 } 170 171 static int 172 /*ARGSUSED*/ 173 _citrus_BIG5_encoding_module_init(_BIG5EncodingInfo * __restrict ei, 174 const void * __restrict var, size_t lenvar) 175 { 176 _DIAGASSERT(ei != NULL); 177 178 memset((void *)ei, 0, sizeof(*ei)); 179 180 return (0); 181 } 182 183 static void 184 /*ARGSUSED*/ 185 _citrus_BIG5_encoding_module_uninit(_BIG5EncodingInfo *ei) 186 { 187 } 188 189 static int 190 /*ARGSUSED*/ 191 _citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei, 192 wchar_t * __restrict pwc, 193 const char ** __restrict s, size_t n, 194 _BIG5State * __restrict psenc, 195 size_t * __restrict nresult) 196 { 197 wchar_t wchar; 198 int c; 199 int chlenbak; 200 const char *s0; 201 202 _DIAGASSERT(nresult != 0); 203 _DIAGASSERT(ei != NULL); 204 _DIAGASSERT(psenc != NULL); 205 _DIAGASSERT(s != NULL && *s != NULL); 206 207 s0 = *s; 208 209 if (s0 == NULL) { 210 _citrus_BIG5_init_state(ei, psenc); 211 *nresult = 0; 212 return (0); 213 } 214 215 chlenbak = psenc->chlen; 216 217 /* make sure we have the first byte in the buffer */ 218 switch (psenc->chlen) { 219 case 0: 220 if (n < 1) 221 goto restart; 222 psenc->ch[0] = *s0++; 223 psenc->chlen = 1; 224 n--; 225 break; 226 case 1: 227 break; 228 default: 229 /* illegal state */ 230 goto ilseq; 231 } 232 233 c = _citrus_BIG5_check(psenc->ch[0] & 0xff); 234 if (c == 0) 235 goto ilseq; 236 while (psenc->chlen < c) { 237 if (n < 1) { 238 goto restart; 239 } 240 psenc->ch[psenc->chlen] = *s0++; 241 psenc->chlen++; 242 n--; 243 } 244 245 switch (c) { 246 case 1: 247 wchar = psenc->ch[0] & 0xff; 248 break; 249 case 2: 250 if (!_citrus_BIG5_check2(psenc->ch[1] & 0xff)) 251 goto ilseq; 252 wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); 253 break; 254 default: 255 /* illegal state */ 256 goto ilseq; 257 } 258 259 *s = s0; 260 psenc->chlen = 0; 261 if (pwc) 262 *pwc = wchar; 263 if (!wchar) 264 *nresult = 0; 265 else 266 *nresult = c - chlenbak; 267 268 return (0); 269 270 ilseq: 271 psenc->chlen = 0; 272 *nresult = (size_t)-1; 273 return (EILSEQ); 274 275 restart: 276 *s = s0; 277 *nresult = (size_t)-2; 278 return (0); 279 } 280 281 static int 282 /*ARGSUSED*/ 283 _citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei, 284 char * __restrict s, 285 size_t n, wchar_t wc, _BIG5State * __restrict psenc, 286 size_t * __restrict nresult) 287 { 288 int l, ret; 289 290 _DIAGASSERT(ei != NULL); 291 _DIAGASSERT(nresult != 0); 292 _DIAGASSERT(s != NULL); 293 294 /* reset state */ 295 if (wc == 0) { 296 *nresult = 0; /* stateless */ 297 return 0; 298 } 299 300 /* check invalid sequence */ 301 if (wc & ~0xffff) { 302 ret = EILSEQ; 303 goto err; 304 } 305 306 if (wc & 0x8000) { 307 if (_citrus_BIG5_check((wc >> 8) & 0xff) != 2 || 308 !_citrus_BIG5_check2(wc & 0xff)) { 309 ret = EILSEQ; 310 goto err; 311 } 312 l = 2; 313 } else { 314 if (wc & ~0xff || !_citrus_BIG5_check(wc & 0xff)) { 315 ret = EILSEQ; 316 goto err; 317 } 318 l = 1; 319 } 320 321 if (n < l) { 322 /* bound check failure */ 323 ret = E2BIG; 324 goto err; 325 } 326 327 if (l == 2) { 328 s[0] = (wc >> 8) & 0xff; 329 s[1] = wc & 0xff; 330 } else 331 s[0] = wc & 0xff; 332 333 *nresult = l; 334 335 return 0; 336 337 err: 338 *nresult = (size_t)-1; 339 return ret; 340 } 341 342 static __inline int 343 /*ARGSUSED*/ 344 _citrus_BIG5_stdenc_wctocs(_BIG5EncodingInfo * __restrict ei, 345 _csid_t * __restrict csid, 346 _index_t * __restrict idx, wchar_t wc) 347 { 348 349 _DIAGASSERT(csid != NULL && idx != NULL); 350 351 if (wc<0x100) 352 *csid = 0; 353 else 354 *csid = 1; 355 *idx = (_index_t)wc; 356 357 return 0; 358 } 359 360 static __inline int 361 /*ARGSUSED*/ 362 _citrus_BIG5_stdenc_cstowc(_BIG5EncodingInfo * __restrict ei, 363 wchar_t * __restrict wc, 364 _csid_t csid, _index_t idx) 365 { 366 u_int8_t h, l; 367 368 _DIAGASSERT(wc != NULL); 369 370 switch (csid) { 371 case 0: 372 if (idx>=0x80U) 373 return EILSEQ; 374 *wc = (wchar_t)idx; 375 break; 376 case 1: 377 if (idx>=0x10000U) 378 return EILSEQ; 379 h = idx >> 8; 380 l = idx; 381 if (h<0xA1 || h>0xF9 || l<0x40 || l>0xFE) 382 return EILSEQ; 383 *wc = (wchar_t)idx; 384 break; 385 default: 386 return EILSEQ; 387 } 388 389 return 0; 390 } 391 392 /* ---------------------------------------------------------------------- 393 * public interface for ctype 394 */ 395 396 _CITRUS_CTYPE_DECLS(BIG5); 397 _CITRUS_CTYPE_DEF_OPS(BIG5); 398 399 #include "citrus_ctype_template.h" 400 401 402 /* ---------------------------------------------------------------------- 403 * public interface for stdenc 404 */ 405 406 _CITRUS_STDENC_DECLS(BIG5); 407 _CITRUS_STDENC_DEF_OPS(BIG5); 408 409 #include "citrus_stdenc_template.h" 410