17a55a3c2SPoul-Henning Kamp /*-
27b247341SBaptiste Daroussin * Copyright 2013 Garrett D'Amore <garrett@damore.org>
37b247341SBaptiste Daroussin * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
4ca2dae42STim J. Robbins * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
57a55a3c2SPoul-Henning Kamp * Copyright (c) 1993
67a55a3c2SPoul-Henning Kamp * The Regents of the University of California. All rights reserved.
77a55a3c2SPoul-Henning Kamp *
87a55a3c2SPoul-Henning Kamp * This code is derived from software contributed to Berkeley by
97a55a3c2SPoul-Henning Kamp * Paul Borman at Krystal Technologies.
107a55a3c2SPoul-Henning Kamp *
113c87aa1dSDavid Chisnall * Copyright (c) 2011 The FreeBSD Foundation
12*5b5fa75aSEd Maste *
133c87aa1dSDavid Chisnall * Portions of this software were developed by David Chisnall
143c87aa1dSDavid Chisnall * under sponsorship from the FreeBSD Foundation.
153c87aa1dSDavid Chisnall *
167a55a3c2SPoul-Henning Kamp * Redistribution and use in source and binary forms, with or without
177a55a3c2SPoul-Henning Kamp * modification, are permitted provided that the following conditions
187a55a3c2SPoul-Henning Kamp * are met:
197a55a3c2SPoul-Henning Kamp * 1. Redistributions of source code must retain the above copyright
207a55a3c2SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer.
217a55a3c2SPoul-Henning Kamp * 2. Redistributions in binary form must reproduce the above copyright
227a55a3c2SPoul-Henning Kamp * notice, this list of conditions and the following disclaimer in the
237a55a3c2SPoul-Henning Kamp * documentation and/or other materials provided with the distribution.
247b247341SBaptiste Daroussin * 3. Neither the name of the University nor the names of its contributors
257a55a3c2SPoul-Henning Kamp * may be used to endorse or promote products derived from this software
267a55a3c2SPoul-Henning Kamp * without specific prior written permission.
277a55a3c2SPoul-Henning Kamp *
287a55a3c2SPoul-Henning Kamp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
297a55a3c2SPoul-Henning Kamp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
307a55a3c2SPoul-Henning Kamp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
317a55a3c2SPoul-Henning Kamp * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
327a55a3c2SPoul-Henning Kamp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
337a55a3c2SPoul-Henning Kamp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
347a55a3c2SPoul-Henning Kamp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
357a55a3c2SPoul-Henning Kamp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
367a55a3c2SPoul-Henning Kamp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
377a55a3c2SPoul-Henning Kamp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
387a55a3c2SPoul-Henning Kamp * SUCH DAMAGE.
397a55a3c2SPoul-Henning Kamp */
407a55a3c2SPoul-Henning Kamp
41e94c6cb4SAlexey Zelkin #include <sys/types.h>
42fc813796STim J. Robbins #include <errno.h>
4302f4f60aSTim J. Robbins #include <runetype.h>
447a55a3c2SPoul-Henning Kamp #include <stdlib.h>
45ca2dae42STim J. Robbins #include <string.h>
4602f4f60aSTim J. Robbins #include <wchar.h>
472051a8f2STim J. Robbins #include "mblocal.h"
4802f4f60aSTim J. Robbins
49367ed4e1SAndrey A. Chernov extern int __mb_sb_limit;
50367ed4e1SAndrey A. Chernov
51e94c6cb4SAlexey Zelkin static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict,
52e94c6cb4SAlexey Zelkin size_t, mbstate_t * __restrict);
53e94c6cb4SAlexey Zelkin static int _BIG5_mbsinit(const mbstate_t *);
54e94c6cb4SAlexey Zelkin static size_t _BIG5_wcrtomb(char * __restrict, wchar_t,
5502f4f60aSTim J. Robbins mbstate_t * __restrict);
567b247341SBaptiste Daroussin static size_t _BIG5_mbsnrtowcs(wchar_t * __restrict,
577b247341SBaptiste Daroussin const char ** __restrict, size_t, size_t,
587b247341SBaptiste Daroussin mbstate_t * __restrict);
597b247341SBaptiste Daroussin static size_t _BIG5_wcsnrtombs(char * __restrict,
607b247341SBaptiste Daroussin const wchar_t ** __restrict, size_t, size_t,
617b247341SBaptiste Daroussin mbstate_t * __restrict);
627a55a3c2SPoul-Henning Kamp
63ca2dae42STim J. Robbins typedef struct {
6461074767STim J. Robbins wchar_t ch;
65ca2dae42STim J. Robbins } _BIG5State;
66ca2dae42STim J. Robbins
677a55a3c2SPoul-Henning Kamp int
_BIG5_init(struct xlocale_ctype * l,_RuneLocale * rl)683c87aa1dSDavid Chisnall _BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl)
697a55a3c2SPoul-Henning Kamp {
7002f4f60aSTim J. Robbins
713c87aa1dSDavid Chisnall l->__mbrtowc = _BIG5_mbrtowc;
723c87aa1dSDavid Chisnall l->__wcrtomb = _BIG5_wcrtomb;
737b247341SBaptiste Daroussin l->__mbsnrtowcs = _BIG5_mbsnrtowcs;
747b247341SBaptiste Daroussin l->__wcsnrtombs = _BIG5_wcsnrtombs;
753c87aa1dSDavid Chisnall l->__mbsinit = _BIG5_mbsinit;
763c87aa1dSDavid Chisnall l->runes = rl;
773c87aa1dSDavid Chisnall l->__mb_cur_max = 2;
783c87aa1dSDavid Chisnall l->__mb_sb_limit = 128;
797a55a3c2SPoul-Henning Kamp return (0);
807a55a3c2SPoul-Henning Kamp }
817a55a3c2SPoul-Henning Kamp
82e94c6cb4SAlexey Zelkin static int
_BIG5_mbsinit(const mbstate_t * ps)83ca2dae42STim J. Robbins _BIG5_mbsinit(const mbstate_t *ps)
84ca2dae42STim J. Robbins {
85ca2dae42STim J. Robbins
8661074767STim J. Robbins return (ps == NULL || ((const _BIG5State *)ps)->ch == 0);
87ca2dae42STim J. Robbins }
88ca2dae42STim J. Robbins
8902f4f60aSTim J. Robbins static __inline int
_big5_check(u_int c)9002f4f60aSTim J. Robbins _big5_check(u_int c)
917a55a3c2SPoul-Henning Kamp {
9202f4f60aSTim J. Robbins
937a55a3c2SPoul-Henning Kamp c &= 0xff;
947a55a3c2SPoul-Henning Kamp return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1);
957a55a3c2SPoul-Henning Kamp }
967a55a3c2SPoul-Henning Kamp
97e94c6cb4SAlexey Zelkin static size_t
_BIG5_mbrtowc(wchar_t * __restrict pwc,const char * __restrict s,size_t n,mbstate_t * __restrict ps)9802f4f60aSTim J. Robbins _BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
99ca2dae42STim J. Robbins mbstate_t * __restrict ps)
1007a55a3c2SPoul-Henning Kamp {
101ca2dae42STim J. Robbins _BIG5State *bs;
10202f4f60aSTim J. Robbins wchar_t wc;
10361074767STim J. Robbins size_t len;
1047a55a3c2SPoul-Henning Kamp
105ca2dae42STim J. Robbins bs = (_BIG5State *)ps;
106ca2dae42STim J. Robbins
10761074767STim J. Robbins if ((bs->ch & ~0xFF) != 0) {
10861074767STim J. Robbins /* Bad conversion state. */
109fc813796STim J. Robbins errno = EINVAL;
110fc813796STim J. Robbins return ((size_t)-1);
111fc813796STim J. Robbins }
112fc813796STim J. Robbins
113ca2dae42STim J. Robbins if (s == NULL) {
114ca2dae42STim J. Robbins s = "";
115ca2dae42STim J. Robbins n = 1;
116ca2dae42STim J. Robbins pwc = NULL;
117ca2dae42STim J. Robbins }
118ca2dae42STim J. Robbins
11961074767STim J. Robbins if (n == 0)
12002f4f60aSTim J. Robbins /* Incomplete multibyte sequence */
12102f4f60aSTim J. Robbins return ((size_t)-2);
12261074767STim J. Robbins
12361074767STim J. Robbins if (bs->ch != 0) {
12461074767STim J. Robbins if (*s == '\0') {
12588af941aSTim J. Robbins errno = EILSEQ;
12688af941aSTim J. Robbins return ((size_t)-1);
12788af941aSTim J. Robbins }
12861074767STim J. Robbins wc = (bs->ch << 8) | (*s & 0xFF);
12902f4f60aSTim J. Robbins if (pwc != NULL)
13002f4f60aSTim J. Robbins *pwc = wc;
13161074767STim J. Robbins bs->ch = 0;
13261074767STim J. Robbins return (1);
13361074767STim J. Robbins }
13461074767STim J. Robbins
13561074767STim J. Robbins len = (size_t)_big5_check(*s);
13661074767STim J. Robbins wc = *s++ & 0xff;
13761074767STim J. Robbins if (len == 2) {
13861074767STim J. Robbins if (n < 2) {
13961074767STim J. Robbins /* Incomplete multibyte sequence */
14061074767STim J. Robbins bs->ch = wc;
14161074767STim J. Robbins return ((size_t)-2);
14261074767STim J. Robbins }
14361074767STim J. Robbins if (*s == '\0') {
14461074767STim J. Robbins errno = EILSEQ;
14561074767STim J. Robbins return ((size_t)-1);
14661074767STim J. Robbins }
14761074767STim J. Robbins wc = (wc << 8) | (*s++ & 0xff);
14861074767STim J. Robbins if (pwc != NULL)
14961074767STim J. Robbins *pwc = wc;
15061074767STim J. Robbins return (2);
15161074767STim J. Robbins } else {
15261074767STim J. Robbins if (pwc != NULL)
15361074767STim J. Robbins *pwc = wc;
15461074767STim J. Robbins return (wc == L'\0' ? 0 : 1);
15561074767STim J. Robbins }
1567a55a3c2SPoul-Henning Kamp }
1577a55a3c2SPoul-Henning Kamp
158e94c6cb4SAlexey Zelkin static size_t
_BIG5_wcrtomb(char * __restrict s,wchar_t wc,mbstate_t * __restrict ps)159fc813796STim J. Robbins _BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
1607a55a3c2SPoul-Henning Kamp {
161fc813796STim J. Robbins _BIG5State *bs;
162fc813796STim J. Robbins
163fc813796STim J. Robbins bs = (_BIG5State *)ps;
164fc813796STim J. Robbins
16561074767STim J. Robbins if (bs->ch != 0) {
166fc813796STim J. Robbins errno = EINVAL;
167fc813796STim J. Robbins return ((size_t)-1);
168fc813796STim J. Robbins }
16902f4f60aSTim J. Robbins
17002f4f60aSTim J. Robbins if (s == NULL)
17102f4f60aSTim J. Robbins /* Reset to initial shift state (no-op) */
17202f4f60aSTim J. Robbins return (1);
17302f4f60aSTim J. Robbins if (wc & 0x8000) {
17402f4f60aSTim J. Robbins *s++ = (wc >> 8) & 0xff;
17502f4f60aSTim J. Robbins *s = wc & 0xff;
1767a55a3c2SPoul-Henning Kamp return (2);
1777a55a3c2SPoul-Henning Kamp }
17802f4f60aSTim J. Robbins *s = wc & 0xff;
1797a55a3c2SPoul-Henning Kamp return (1);
1807a55a3c2SPoul-Henning Kamp }
1817b247341SBaptiste Daroussin
1827b247341SBaptiste Daroussin static size_t
_BIG5_mbsnrtowcs(wchar_t * __restrict dst,const char ** __restrict src,size_t nms,size_t len,mbstate_t * __restrict ps)1837b247341SBaptiste Daroussin _BIG5_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
1847b247341SBaptiste Daroussin size_t nms, size_t len, mbstate_t * __restrict ps)
1857b247341SBaptiste Daroussin {
1867b247341SBaptiste Daroussin return (__mbsnrtowcs_std(dst, src, nms, len, ps, _BIG5_mbrtowc));
1877b247341SBaptiste Daroussin }
1887b247341SBaptiste Daroussin
1897b247341SBaptiste Daroussin static size_t
_BIG5_wcsnrtombs(char * __restrict dst,const wchar_t ** __restrict src,size_t nwc,size_t len,mbstate_t * __restrict ps)1907b247341SBaptiste Daroussin _BIG5_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
1917b247341SBaptiste Daroussin size_t nwc, size_t len, mbstate_t * __restrict ps)
1927b247341SBaptiste Daroussin {
1937b247341SBaptiste Daroussin return (__wcsnrtombs_std(dst, src, nwc, len, ps, _BIG5_wcrtomb));
1947b247341SBaptiste Daroussin }
195