big5.c revision 129117
151974Smsmith/*- 265245Smsmith * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. 365245Smsmith * Copyright (c) 1993 451974Smsmith * The Regents of the University of California. All rights reserved. 551974Smsmith * 651974Smsmith * This code is derived from software contributed to Berkeley by 751974Smsmith * Paul Borman at Krystal Technologies. 851974Smsmith * 951974Smsmith * Redistribution and use in source and binary forms, with or without 1051974Smsmith * modification, are permitted provided that the following conditions 1151974Smsmith * are met: 1251974Smsmith * 1. Redistributions of source code must retain the above copyright 1351974Smsmith * notice, this list of conditions and the following disclaimer. 1451974Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1551974Smsmith * notice, this list of conditions and the following disclaimer in the 1651974Smsmith * documentation and/or other materials provided with the distribution. 1751974Smsmith * 3. All advertising materials mentioning features or use of this software 1851974Smsmith * must display the following acknowledgement: 1951974Smsmith * This product includes software developed by the University of 2051974Smsmith * California, Berkeley and its contributors. 2151974Smsmith * 4. Neither the name of the University nor the names of its contributors 2251974Smsmith * may be used to endorse or promote products derived from this software 2351974Smsmith * without specific prior written permission. 2451974Smsmith * 2551974Smsmith * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2651974Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27106225Semoore * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28106225Semoore * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29106225Semoore * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30106225Semoore * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31106225Semoore * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32106225Semoore * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33106225Semoore * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34106225Semoore * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35106225Semoore * SUCH DAMAGE. 36106225Semoore */ 37106225Semoore 38106225Semoore#if defined(LIBC_SCCS) && !defined(lint) 39105419Semoorestatic char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93"; 40106225Semoore#endif /* LIBC_SCCS and not lint */ 41105419Semoore#include <sys/param.h> 42105419Semoore__FBSDID("$FreeBSD: head/lib/libc/locale/big5.c 129117 2004-05-11 14:08:22Z tjr $"); 43106225Semoore 44106225Semoore#include <errno.h> 45106225Semoore#include <runetype.h> 46106225Semoore#include <stdlib.h> 47106225Semoore#include <string.h> 48106225Semoore#include <wchar.h> 49106225Semoore 50106225Semooreextern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, 51106225Semoore size_t, mbstate_t * __restrict); 52106225Semooreextern int (*__mbsinit)(const mbstate_t *); 53106225Semooreextern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); 54105419Semoore 55106225Semooreint _BIG5_init(_RuneLocale *); 5651974Smsmithsize_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, 5751974Smsmith mbstate_t * __restrict); 5851974Smsmithint _BIG5_mbsinit(const mbstate_t *); 5965245Smsmithsize_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); 60112946Sphk 61140340Sscottltypedef struct { 62140340Sscottl int count; 6365245Smsmith u_char bytes[2]; 6451974Smsmith} _BIG5State; 6565245Smsmith 6687599Sobrienint 6787599Sobrien_BIG5_init(_RuneLocale *rl) 6865245Smsmith{ 6965245Smsmith 7065245Smsmith __mbrtowc = _BIG5_mbrtowc; 7165245Smsmith __wcrtomb = _BIG5_wcrtomb; 7287599Sobrien __mbsinit = _BIG5_mbsinit; 7351974Smsmith _CurrentRuneLocale = rl; 7451974Smsmith __mb_cur_max = 2; 7551974Smsmith return (0); 7651974Smsmith} 7751974Smsmith 7851974Smsmithint 7951974Smsmith_BIG5_mbsinit(const mbstate_t *ps) 8051974Smsmith{ 8151974Smsmith 8251974Smsmith return (ps == NULL || ((const _BIG5State *)ps)->count == 0); 8351974Smsmith} 8451974Smsmith 8551974Smsmithstatic __inline int 8651974Smsmith_big5_check(u_int c) 8751974Smsmith{ 8851974Smsmith 8951974Smsmith c &= 0xff; 9051974Smsmith return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1); 9151974Smsmith} 9265245Smsmith 9365245Smsmithsize_t 9465245Smsmith_BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, 9565245Smsmith mbstate_t * __restrict ps) 9665245Smsmith{ 9765245Smsmith _BIG5State *bs; 9865245Smsmith wchar_t wc; 9965245Smsmith int i, len, ocount; 10051974Smsmith size_t ncopy; 10165245Smsmith 10265245Smsmith bs = (_BIG5State *)ps; 10351974Smsmith 10451974Smsmith if (bs->count < 0 || bs->count > sizeof(bs->bytes)) { 10551974Smsmith errno = EINVAL; 10651974Smsmith return ((size_t)-1); 10751974Smsmith } 10860938Sjake 10951974Smsmith if (s == NULL) { 11051974Smsmith s = ""; 11151974Smsmith n = 1; 11265245Smsmith pwc = NULL; 11351974Smsmith } 11451974Smsmith 11551974Smsmith ncopy = MIN(MIN(n, MB_CUR_MAX), sizeof(bs->bytes) - bs->count); 11651974Smsmith memcpy(bs->bytes + bs->count, s, ncopy); 11765245Smsmith ocount = bs->count; 11865245Smsmith bs->count += ncopy; 11965245Smsmith s = (char *)bs->bytes; 12065245Smsmith n = bs->count; 12165245Smsmith 12265245Smsmith if (n == 0 || (size_t)(len = _big5_check(*s)) > n) 12351974Smsmith /* Incomplete multibyte sequence */ 12465245Smsmith return ((size_t)-2); 12565245Smsmith if (n == 2 && s[1] == '\0') { 12651974Smsmith errno = EILSEQ; 12751974Smsmith return ((size_t)-1); 12851974Smsmith } 12951974Smsmith wc = 0; 13051974Smsmith i = len; 13165245Smsmith while (i-- > 0) 13265245Smsmith wc = (wc << 8) | (unsigned char)*s++; 13365245Smsmith if (pwc != NULL) 13465245Smsmith *pwc = wc; 13565245Smsmith bs->count = 0; 13651974Smsmith return (wc == L'\0' ? 0 : len - ocount); 137105419Semoore} 13851974Smsmith 13951974Smsmithsize_t 14065245Smsmith_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) 14165245Smsmith{ 14265245Smsmith _BIG5State *bs; 14365245Smsmith 14465245Smsmith bs = (_BIG5State *)ps; 14565245Smsmith 14665245Smsmith if (bs->count != 0) { 14765245Smsmith errno = EINVAL; 14865245Smsmith return ((size_t)-1); 14965245Smsmith } 15065245Smsmith 15165245Smsmith if (s == NULL) 15251974Smsmith /* Reset to initial shift state (no-op) */ 15351974Smsmith return (1); 15451974Smsmith if (wc & 0x8000) { 15551974Smsmith *s++ = (wc >> 8) & 0xff; 15651974Smsmith *s = wc & 0xff; 15751974Smsmith return (2); 15851974Smsmith } 15951974Smsmith *s = wc & 0xff; 16051974Smsmith return (1); 16151974Smsmith} 16251974Smsmith