xref: /titanic_51/usr/src/lib/iconv_modules/zh/common/zh_HK.hkscs%zh_CN.gbk.c (revision 91e1e26ac6a73ce959289cf7d3d96c4baedbe0b8)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  *	Copyright(c) 2001 Sun Microsystems, Inc.
23  *	All rights reserved.
24  */
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <errno.h>
28 #include <big5hk_gb18030.h>
29 
30 #define NON_ID_CHAR '_'	/* non-identifier charactor */
31 #define MSB 0x80
32 #define ONEBYTE 0xff
33 #define gbk_4th_byte(v)  ( ((v) >= 0x30) && ((v) <= 0x39) )
34 
35 typedef struct _icv_state {
36 	char keepc[2];	/* maximum # byte of HKSCS charactor */
37 	short cstate;
38 	int _errno;		/* internal errno */
39 } _iconv_st;
40 
41 enum _CSTATE { C0, C1 };
42 
43 int binsearch(unsigned long x, table_t table[], int n);
44 int hkscs_2nd_byte(char inbuf);
45 int hkscs_to_gbk2k(char keepc[], char *buf, size_t buflen);
46 
47 /*
48  *	Open; called from iconv_open()
49  */
50 void * _icv_open() {
51 	_iconv_st * st;
52 
53 	if ((st = (_iconv_st *) malloc(sizeof(_iconv_st))) == NULL) {
54 		errno = ENOMEM;
55 		return ((void *) -1);
56 	}
57 
58 	st->cstate = C0;
59 	st->_errno = 0;
60 
61 	return ((void *) st);
62 }
63 
64 /*
65  *	Close; called from iconv_close()
66  */
67 void _icv_close(_iconv_st * st) {
68 	if (!st)
69 		errno = EBADF;
70 	else
71 		free(st);
72 }
73 
74 /*
75  *	Actual conversion; called from iconv()
76  */
77 
78 size_t _icv_iconv(_iconv_st * st, char **inbuf, size_t *inbytesleft,
79 					char ** outbuf, size_t *outbytesleft) {
80 	int n;
81 	if (st == NULL) {
82 		errno = EBADF;
83 		return ((size_t) -1);
84 	}
85 
86 	if (inbuf == NULL || *inbuf == NULL) {	/* Reset request. */
87 		st->cstate = C0;
88 		st->_errno = 0;
89 		return ((size_t) 0);
90 	}
91 
92 	errno = st->_errno = 0;
93 
94 	while (*inbytesleft > 0 && *outbytesleft > 0) {
95 		switch (st->cstate) {
96 			case C0:
97 				if (**inbuf & MSB) {	/* hkscs charactor */
98 					st->keepc[0] = (**inbuf);
99 					st->cstate = C1;
100 				} else {	/* ASCII */
101 					**outbuf = **inbuf;
102 					(*outbuf)++;
103 					(*outbytesleft)--;
104 				}
105 				break;
106 			case C1:	/* hkscs charactor 2nd byte */
107 				if (hkscs_2nd_byte(**inbuf) == 0) {
108 					st->keepc[1] = (**inbuf);
109 					n = hkscs_to_gbk2k(st->keepc, *outbuf, *outbytesleft);
110 					if (n > 0) {
111 						(*outbuf) += n;
112 						(*outbytesleft) -= n;
113 
114 						st->cstate = C0;
115 					} else {
116 						st->_errno = errno = E2BIG;
117 					}
118 				} else {	/* illegal input */
119 					st->_errno = errno =EILSEQ;
120 				}
121 				break;
122 			default:
123 				st->_errno = errno = EILSEQ;
124 				st->cstate = C0;
125 				break;
126 		}
127 
128 		if (st->_errno) break;
129 
130 		(*inbuf) ++;
131 		(*inbytesleft)--;
132 
133 	}
134 
135 	if (errno) return ((size_t) -1);
136 
137 	if (*inbytesleft == 0 && st->cstate != C0) {
138 		errno = EINVAL;
139 		return ((size_t) -1);
140 	}
141 
142 	if (*inbytesleft > 0 && *outbytesleft == 0) {
143 		errno = E2BIG;
144 		return (size_t)-1;
145 	}
146 
147 	return (size_t)(*inbytesleft);
148 }
149 
150 /*
151  *	Test whether inbuf is a valid character for
152  *	2nd byte of HKSCS charactor:
153  *	Return:	0 --- valid HKSCS 2nd byte
154  *			1 --- invalid HKSCS 2nd byte
155  */
156 int hkscs_2nd_byte(inbuf)
157 char inbuf;
158 {
159 	unsigned int buf = (unsigned int)(inbuf & ONEBYTE);
160 
161 	if ((buf >= 0x40) && (buf <= 0xfe))
162 		return 0;
163 	return 1;
164 }
165 
166 /*
167  *	hkscs_to_gbk2k: Convert hkscs to gbk.
168  *	Return:	>0 --- converted with enough space in output buffer
169  *			=0 --- no space in outbuf
170  */
171 
172 int hkscs_to_gbk2k(char keepc[], char *buf, size_t buflen) {
173 
174 	unsigned long gbk_val;
175 	int index, len;
176 	unsigned long hkscs_val;
177 
178 	if (buflen < 2) {
179 		errno = E2BIG;
180 		return 0;
181 	}
182 
183 	hkscs_val = ((keepc[0] & ONEBYTE) << 8) + (keepc[1] & ONEBYTE);
184 	index = binsearch(hkscs_val, hkscs_gbk2k_tab, MAX_HKSCS_NUM);
185 	if (index >= 0) {
186 		char c;
187 
188 		gbk_val = hkscs_gbk2k_tab[index].value;
189 		c =  gbk_val & ONEBYTE;
190 		if ( gbk_4th_byte( (unsigned char)c ) ) {
191 
192 			if ( buflen < 4 ) {
193 				errno = E2BIG;
194 				return 0;
195 			}
196 
197 			*buf = ( gbk_val >> 24) & ONEBYTE;
198 			*(buf + 1) = (gbk_val >> 16) & ONEBYTE;
199 			*(buf + 2) = (gbk_val >> 8) & ONEBYTE;
200 			*(buf + 3) = c;
201 
202 			len = 4;
203 		} else {
204 			*buf = (gbk_val >> 8) & ONEBYTE;
205 			*(buf + 1) = c;
206 
207 			len = 2;
208 		}
209 	} else {
210 		*buf = *(buf + 1) = (char)NON_ID_CHAR;
211 		len = 2;
212 	}
213 	return len;
214 }
215 
216 /*
217  *	binsearch()
218  */
219 int binsearch(unsigned long x, table_t table[], int n) {
220 	int low, high, mid;
221 
222 	low = 0;
223 	high = n - 1;
224 	while (low <= high) {
225 		mid = (low + high) >> 1;
226 		if (x < table[mid].key)
227 			high = mid - 1;
228 		else if (x > table[mid].key)
229 			low = mid + 1;
230 		else
231 			return mid;
232 	}
233 	return -1;
234 }
235