1 /* $NetBSD: citrus_big5.c,v 1.5 2002/03/28 10:53:48 yamt 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.5 2002/03/28 10:53:48 yamt 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 #include "citrus_module.h" 81 #include "citrus_ctype.h" 82 #include "citrus_big5.h" 83 84 /* ---------------------------------------------------------------------- 85 * private stuffs used by templates 86 */ 87 88 typedef struct { 89 char ch[2]; 90 int chlen; 91 } _BIG5State; 92 93 typedef struct { 94 int dummy; 95 } _BIG5EncodingInfo; 96 97 typedef struct { 98 _BIG5EncodingInfo ei; 99 struct { 100 /* for future multi-locale facility */ 101 _BIG5State s_mblen; 102 _BIG5State s_mbrlen; 103 _BIG5State s_mbrtowc; 104 _BIG5State s_mbtowc; 105 _BIG5State s_mbsrtowcs; 106 _BIG5State s_wcrtomb; 107 _BIG5State s_wcsrtombs; 108 _BIG5State s_wctomb; 109 } states; 110 } _BIG5CTypeInfo; 111 112 #define _CEI_TO_EI(_cei_) (&(_cei_)->ei) 113 #define _CEI_TO_STATE(_cei_, _func_) (_cei_)->states.s_##_func_ 114 115 #define _FUNCNAME(m) _citrus_BIG5_##m 116 #define _ENCODING_INFO _BIG5EncodingInfo 117 #define _CTYPE_INFO _BIG5CTypeInfo 118 #define _ENCODING_STATE _BIG5State 119 #define _ENCODING_MB_CUR_MAX(_ei_) 2 120 #define _ENCODING_IS_STATE_DEPENDENT 0 121 #define _STATE_NEEDS_EXPLICIT_INIT(_ps_) 0 122 123 124 static __inline void 125 /*ARGSUSED*/ 126 _citrus_BIG5_init_state(_BIG5EncodingInfo * __restrict ei, 127 _BIG5State * __restrict s) 128 { 129 memset(s, 0, sizeof(*s)); 130 } 131 132 static __inline void 133 /*ARGSUSED*/ 134 _citrus_BIG5_pack_state(_BIG5EncodingInfo * __restrict ei, 135 void * __restrict pspriv, 136 const _BIG5State * __restrict s) 137 { 138 memcpy(pspriv, (const void *)s, sizeof(*s)); 139 } 140 141 static __inline void 142 /*ARGSUSED*/ 143 _citrus_BIG5_unpack_state(_BIG5EncodingInfo * __restrict ei, 144 _BIG5State * __restrict s, 145 const void * __restrict pspriv) 146 { 147 memcpy((void *)s, pspriv, sizeof(*s)); 148 } 149 150 static __inline int 151 _citrus_BIG5_check(u_int c) 152 { 153 c &= 0xff; 154 return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1); 155 } 156 157 static __inline int 158 _citrus_BIG5_check2(u_int c) 159 { 160 c &= 0xff; 161 if ((c >= 0x40 && c <= 0x7f) || (c >= 0xa1 && c <= 0xfe)) 162 return 1; 163 else 164 return 0; 165 } 166 167 static int 168 /*ARGSUSED*/ 169 _citrus_BIG5_stdencoding_init(_BIG5EncodingInfo * __restrict ei, 170 const void * __restrict var, size_t lenvar) 171 { 172 _DIAGASSERT(ei != NULL); 173 174 memset((void *)ei, 0, sizeof(*ei)); 175 176 return (0); 177 } 178 179 static void 180 /*ARGSUSED*/ 181 _citrus_BIG5_stdencoding_uninit(_BIG5EncodingInfo *ei) 182 { 183 } 184 185 static int 186 /*ARGSUSED*/ 187 _citrus_BIG5_mbrtowc_priv(_BIG5EncodingInfo * __restrict ei, 188 wchar_t * __restrict pwc, 189 const char ** __restrict s, size_t n, 190 _BIG5State * __restrict psenc, 191 size_t * __restrict nresult) 192 { 193 wchar_t wchar; 194 int c; 195 int chlenbak; 196 const char *s0; 197 198 _DIAGASSERT(nresult != 0); 199 _DIAGASSERT(ei != NULL); 200 _DIAGASSERT(psenc != NULL); 201 _DIAGASSERT(s != NULL && *s != NULL); 202 203 s0 = *s; 204 205 if (s0 == NULL) { 206 _citrus_BIG5_init_state(ei, psenc); 207 *nresult = 0; 208 return (0); 209 } 210 211 chlenbak = psenc->chlen; 212 213 /* make sure we have the first byte in the buffer */ 214 switch (psenc->chlen) { 215 case 0: 216 if (n < 1) 217 goto restart; 218 psenc->ch[0] = *s0++; 219 psenc->chlen = 1; 220 n--; 221 break; 222 case 1: 223 break; 224 default: 225 /* illegal state */ 226 goto ilseq; 227 } 228 229 c = _citrus_BIG5_check(psenc->ch[0] & 0xff); 230 if (c == 0) 231 goto ilseq; 232 while (psenc->chlen < c) { 233 if (n < 1) { 234 goto restart; 235 } 236 psenc->ch[psenc->chlen] = *s0++; 237 psenc->chlen++; 238 n--; 239 } 240 241 switch (c) { 242 case 1: 243 wchar = psenc->ch[0] & 0xff; 244 break; 245 case 2: 246 if (!_citrus_BIG5_check2(psenc->ch[1] & 0xff)) 247 goto ilseq; 248 wchar = ((psenc->ch[0] & 0xff) << 8) | (psenc->ch[1] & 0xff); 249 break; 250 default: 251 /* illegal state */ 252 goto ilseq; 253 } 254 255 *s = s0; 256 psenc->chlen = 0; 257 if (pwc) 258 *pwc = wchar; 259 if (!wchar) 260 *nresult = 0; 261 else 262 *nresult = c - chlenbak; 263 264 return (0); 265 266 ilseq: 267 psenc->chlen = 0; 268 *nresult = (size_t)-1; 269 return (EILSEQ); 270 271 restart: 272 *s = s0; 273 *nresult = (size_t)-2; 274 return (0); 275 } 276 277 static int 278 /*ARGSUSED*/ 279 _citrus_BIG5_wcrtomb_priv(_BIG5EncodingInfo * __restrict ei, 280 char * __restrict s, 281 size_t n, wchar_t wc, _BIG5State * __restrict psenc, 282 size_t * __restrict nresult) 283 { 284 int l; 285 286 _DIAGASSERT(ei != NULL); 287 _DIAGASSERT(nresult != 0); 288 _DIAGASSERT(s != NULL); 289 290 /* check invalid sequence */ 291 if (wc & ~0xffff) 292 goto ilseq; 293 294 if (wc & 0x8000) { 295 if (_citrus_BIG5_check((wc >> 8) & 0xff) != 2 || 296 !_citrus_BIG5_check2(wc & 0xff)) 297 goto ilseq; 298 l = 2; 299 } else { 300 if (wc & ~0xff || !_citrus_BIG5_check(wc & 0xff)) 301 goto ilseq; 302 l = 1; 303 } 304 305 if (n < l) { 306 /* bound check failure */ 307 goto ilseq; 308 } 309 310 if (l == 2) { 311 s[0] = (wc >> 8) & 0xff; 312 s[1] = wc & 0xff; 313 } else 314 s[0] = wc & 0xff; 315 316 *nresult = l; 317 318 return (0); 319 320 ilseq: 321 *nresult = (size_t)-1; 322 return (EILSEQ); 323 } 324 325 326 /* ---------------------------------------------------------------------- 327 * public interface for ctype 328 */ 329 330 _CITRUS_CTYPE_DECLS(BIG5); 331 _CITRUS_CTYPE_DEF_OPS(BIG5); 332 333 #include "citrus_ctype_template.h" 334