gb2312.c revision 122145
1122145Sdavidxu/*- 2122145Sdavidxu * Copyright (c) 2003 David Xu <davidxu@freebsd.org> 3122145Sdavidxu * All rights reserved. 4122145Sdavidxu * 5122145Sdavidxu * Redistribution and use in source and binary forms, with or without 6122145Sdavidxu * modification, are permitted provided that the following conditions 7122145Sdavidxu * are met: 8122145Sdavidxu * 1. Redistributions of source code must retain the above copyright 9122145Sdavidxu * notice, this list of conditions and the following disclaimer. 10122145Sdavidxu * 2. Redistributions in binary form must reproduce the above copyright 11122145Sdavidxu * notice, this list of conditions and the following disclaimer in the 12122145Sdavidxu * documentation and/or other materials provided with the distribution. 13122145Sdavidxu * 14122145Sdavidxu * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15122145Sdavidxu * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16122145Sdavidxu * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17122145Sdavidxu * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18122145Sdavidxu * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19122145Sdavidxu * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20122145Sdavidxu * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21122145Sdavidxu * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22122145Sdavidxu * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23122145Sdavidxu * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24122145Sdavidxu * SUCH DAMAGE. 25122145Sdavidxu */ 26122145Sdavidxu 27122145Sdavidxu#include <sys/cdefs.h> 28122145Sdavidxu__FBSDID("$FreeBSD: head/lib/libc/locale/gb2312.c 122145 2003-11-05 22:52:51Z davidxu $"); 29122145Sdavidxu 30122145Sdavidxu#include <sys/types.h> 31122145Sdavidxu#include <runetype.h> 32122145Sdavidxu#include <stddef.h> 33122145Sdavidxu#include <stdio.h> 34122145Sdavidxu#include <stdlib.h> 35122145Sdavidxu#include <wchar.h> 36122145Sdavidxu 37122145Sdavidxuextern size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, 38122145Sdavidxu size_t, mbstate_t * __restrict); 39122145Sdavidxuextern size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict); 40122145Sdavidxu 41122145Sdavidxuint _GB2312_init(_RuneLocale *); 42122145Sdavidxusize_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict, size_t, 43122145Sdavidxu mbstate_t * __restrict); 44122145Sdavidxusize_t _GB2312_wcrtomb(char * __restrict, wchar_t, mbstate_t * __restrict); 45122145Sdavidxu 46122145Sdavidxuint 47122145Sdavidxu_GB2312_init(_RuneLocale *rl) 48122145Sdavidxu{ 49122145Sdavidxu 50122145Sdavidxu _CurrentRuneLocale = rl; 51122145Sdavidxu __mbrtowc = _GB2312_mbrtowc; 52122145Sdavidxu __wcrtomb = _GB2312_wcrtomb; 53122145Sdavidxu __mb_cur_max = 2; 54122145Sdavidxu return (0); 55122145Sdavidxu} 56122145Sdavidxu 57122145Sdavidxustatic inline int 58122145Sdavidxu_GB2312_check(const char *str, size_t n) 59122145Sdavidxu{ 60122145Sdavidxu const u_char *s = (const u_char *)str; 61122145Sdavidxu 62122145Sdavidxu if (n == 0) 63122145Sdavidxu /* Incomplete multibyte sequence */ 64122145Sdavidxu return (-2); 65122145Sdavidxu if (s[0] >= 0xa1 && s[0] <= 0xfe) { 66122145Sdavidxu if (n < 2) 67122145Sdavidxu /* Incomplete multibyte sequence */ 68122145Sdavidxu return (-2); 69122145Sdavidxu if (s[1] < 0xa1 || s[1] > 0xfe) 70122145Sdavidxu /* Invalid multibyte sequence */ 71122145Sdavidxu return (-1); 72122145Sdavidxu return (2); 73122145Sdavidxu } else if (s[0] & 0x80) { 74122145Sdavidxu /* Invalid multibyte sequence */ 75122145Sdavidxu return (-1); 76122145Sdavidxu } 77122145Sdavidxu return (1); 78122145Sdavidxu} 79122145Sdavidxu 80122145Sdavidxusize_t 81122145Sdavidxu_GB2312_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n, 82122145Sdavidxu mbstate_t * __restrict ps __unused) 83122145Sdavidxu{ 84122145Sdavidxu wchar_t wc; 85122145Sdavidxu int i, len; 86122145Sdavidxu 87122145Sdavidxu if (s == NULL) 88122145Sdavidxu /* Reset to initial shift state (no-op) */ 89122145Sdavidxu return (0); 90122145Sdavidxu if ((len = _GB2312_check(s, n)) < 0) 91122145Sdavidxu return ((size_t)len); 92122145Sdavidxu wc = 0; 93122145Sdavidxu i = len; 94122145Sdavidxu while (i-- > 0) 95122145Sdavidxu wc = (wc << 8) | (unsigned char)*s++; 96122145Sdavidxu if (pwc != NULL) 97122145Sdavidxu *pwc = wc; 98122145Sdavidxu return (wc == L'\0' ? 0 : len); 99122145Sdavidxu} 100122145Sdavidxu 101122145Sdavidxusize_t 102122145Sdavidxu_GB2312_wcrtomb(char * __restrict s, wchar_t wc, 103122145Sdavidxu mbstate_t * __restrict ps __unused) 104122145Sdavidxu{ 105122145Sdavidxu 106122145Sdavidxu if (s == NULL) 107122145Sdavidxu /* Reset to initial shift state (no-op) */ 108122145Sdavidxu return (1); 109122145Sdavidxu if (wc & 0x8000) { 110122145Sdavidxu *s++ = (wc >> 8) & 0xff; 111122145Sdavidxu *s = wc & 0xff; 112122145Sdavidxu return (2); 113122145Sdavidxu } 114122145Sdavidxu *s = wc & 0xff; 115122145Sdavidxu return (1); 116122145Sdavidxu} 117