big5.c revision 129334
1254721Semaste/*- 2254721Semaste * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved. 3254721Semaste * Copyright (c) 1993 4254721Semaste * The Regents of the University of California. All rights reserved. 5254721Semaste * 6254721Semaste * This code is derived from software contributed to Berkeley by 7254721Semaste * Paul Borman at Krystal Technologies. 8254721Semaste * 9254721Semaste * Redistribution and use in source and binary forms, with or without 10254721Semaste * modification, are permitted provided that the following conditions 11254721Semaste * are met: 12254721Semaste * 1. Redistributions of source code must retain the above copyright 13254721Semaste * notice, this list of conditions and the following disclaimer. 14254721Semaste * 2. Redistributions in binary form must reproduce the above copyright 15254721Semaste * notice, this list of conditions and the following disclaimer in the 16254721Semaste * documentation and/or other materials provided with the distribution. 17254721Semaste * 3. All advertising materials mentioning features or use of this software 18254721Semaste * must display the following acknowledgement: 19254721Semaste * This product includes software developed by the University of 20254721Semaste * California, Berkeley and its contributors. 21254721Semaste * 4. Neither the name of the University nor the names of its contributors 22254721Semaste * may be used to endorse or promote products derived from this software 23254721Semaste * without specific prior written permission. 24254721Semaste * 25254721Semaste * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26254721Semaste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27254721Semaste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28254721Semaste * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29254721Semaste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30254721Semaste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31254721Semaste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32254721Semaste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33254721Semaste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34254721Semaste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35254721Semaste * SUCH DAMAGE. 36254721Semaste */ 37254721Semaste 38254721Semaste#if defined(LIBC_SCCS) && !defined(lint) 39254721Semastestatic char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93"; 40254721Semaste#endif /* LIBC_SCCS and not lint */ 41254721Semaste#include <sys/param.h> 42254721Semaste__FBSDID("$FreeBSD: head/lib/libc/locale/big5.c 129334 2004-05-17 11:16:14Z tjr $"); 43254721Semaste 44254721Semaste#include <errno.h> 45254721Semaste#include <runetype.h> 46254721Semaste#include <stdlib.h> 47254721Semaste#include <string.h> 48254721Semaste#include <wchar.h> 49254721Semaste#include "mblocal.h" 50254721Semaste 51254721Semasteint _BIG5_init(_RuneLocale *); 52254721Semastesize_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, 53254721Semaste mbstate_t * __restrict); 54254721Semasteint _BIG5_mbsinit(const mbstate_t *); 55254721Semastesize_t _BIG5_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); 56254721Semaste 57254721Semastetypedef struct { 58254721Semaste wchar_t ch; 59254721Semaste} _BIG5State; 60254721Semaste 61254721Semasteint 62254721Semaste_BIG5_init(_RuneLocale *rl) 63254721Semaste{ 64254721Semaste 65254721Semaste __mbrtowc = _BIG5_mbrtowc; 66254721Semaste __wcrtomb = _BIG5_wcrtomb; 67254721Semaste __mbsinit = _BIG5_mbsinit; 68254721Semaste _CurrentRuneLocale = rl; 69254721Semaste __mb_cur_max = 2; 70254721Semaste return (0); 71254721Semaste} 72254721Semaste 73254721Semasteint 74254721Semaste_BIG5_mbsinit(const mbstate_t *ps) 75254721Semaste{ 76254721Semaste 77254721Semaste return (ps == NULL || ((const _BIG5State *)ps)->ch == 0); 78254721Semaste} 79254721Semaste 80254721Semastestatic __inline int 81254721Semaste_big5_check(u_int c) 82254721Semaste{ 83254721Semaste 84254721Semaste c &= 0xff; 85254721Semaste return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1); 86254721Semaste} 87254721Semaste 88254721Semastesize_t 89254721Semaste_BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, 90254721Semaste mbstate_t * __restrict ps) 91263363Semaste{ 92263363Semaste _BIG5State *bs; 93254721Semaste wchar_t wc; 94254721Semaste size_t len; 95254721Semaste 96254721Semaste bs = (_BIG5State *)ps; 97254721Semaste 98254721Semaste if ((bs->ch & ~0xFF) != 0) { 99254721Semaste /* Bad conversion state. */ 100254721Semaste errno = EINVAL; 101254721Semaste return ((size_t)-1); 102254721Semaste } 103254721Semaste 104254721Semaste if (s == NULL) { 105254721Semaste s = ""; 106254721Semaste n = 1; 107254721Semaste pwc = NULL; 108254721Semaste } 109254721Semaste 110254721Semaste if (n == 0) 111254721Semaste /* Incomplete multibyte sequence */ 112254721Semaste return ((size_t)-2); 113254721Semaste 114254721Semaste if (bs->ch != 0) { 115254721Semaste if (*s == '\0') { 116254721Semaste errno = EILSEQ; 117254721Semaste return ((size_t)-1); 118254721Semaste } 119254721Semaste wc = (bs->ch << 8) | (*s & 0xFF); 120254721Semaste if (pwc != NULL) 121254721Semaste *pwc = wc; 122254721Semaste bs->ch = 0; 123254721Semaste return (1); 124254721Semaste } 125254721Semaste 126254721Semaste len = (size_t)_big5_check(*s); 127254721Semaste wc = *s++ & 0xff; 128254721Semaste if (len == 2) { 129254721Semaste if (n < 2) { 130254721Semaste /* Incomplete multibyte sequence */ 131254721Semaste bs->ch = wc; 132254721Semaste return ((size_t)-2); 133254721Semaste } 134254721Semaste if (*s == '\0') { 135254721Semaste errno = EILSEQ; 136254721Semaste return ((size_t)-1); 137254721Semaste } 138254721Semaste wc = (wc << 8) | (*s++ & 0xff); 139254721Semaste if (pwc != NULL) 140254721Semaste *pwc = wc; 141254721Semaste return (2); 142254721Semaste } else { 143254721Semaste if (pwc != NULL) 144254721Semaste *pwc = wc; 145254721Semaste return (wc == L'\0' ? 0 : 1); 146254721Semaste } 147254721Semaste} 148254721Semaste 149254721Semastesize_t 150254721Semaste_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps) 151254721Semaste{ 152254721Semaste _BIG5State *bs; 153254721Semaste 154254721Semaste bs = (_BIG5State *)ps; 155254721Semaste 156254721Semaste if (bs->ch != 0) { 157254721Semaste errno = EINVAL; 158254721Semaste return ((size_t)-1); 159 } 160 161 if (s == NULL) 162 /* Reset to initial shift state (no-op) */ 163 return (1); 164 if (wc & 0x8000) { 165 *s++ = (wc >> 8) & 0xff; 166 *s = wc & 0xff; 167 return (2); 168 } 169 *s = wc & 0xff; 170 return (1); 171} 172