summaryrefslogtreecommitdiff
path: root/usr/src/lib/iconv_modules/zh/common/zh_TW-big5p%zh_HK.hkscs.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/iconv_modules/zh/common/zh_TW-big5p%zh_HK.hkscs.c')
-rw-r--r--usr/src/lib/iconv_modules/zh/common/zh_TW-big5p%zh_HK.hkscs.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/usr/src/lib/iconv_modules/zh/common/zh_TW-big5p%zh_HK.hkscs.c b/usr/src/lib/iconv_modules/zh/common/zh_TW-big5p%zh_HK.hkscs.c
new file mode 100644
index 0000000000..6827f0f10a
--- /dev/null
+++ b/usr/src/lib/iconv_modules/zh/common/zh_TW-big5p%zh_HK.hkscs.c
@@ -0,0 +1,211 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright(c) 2001 Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <big5p_big5hk.h>
+
+#define NON_ID_CHAR '_' /* non-identifier charactor */
+#define MSB 0x80
+#define ONEBYTE 0xff
+
+typedef struct _icv_state {
+ char keepc[2]; /* maximum # byte of BIG5 charactor */
+ short cstate;
+ int _errno; /* internal errno */
+} _iconv_st;
+
+enum _CSTATE { C0, C1 };
+
+int big5_2nd_byte(char inbuf);
+int big5p_to_hkscs(char keepc[], char *buf, size_t buflen);
+int binsearch(unsigned long x, table_t table[], int n);
+
+/*
+ * Open; called from iconv_open()
+ */
+void * _icv_open() {
+ _iconv_st * st;
+
+ if ((st = (_iconv_st *) malloc(sizeof(_iconv_st))) == NULL) {
+ errno = ENOMEM;
+ return ((void *) -1);
+ }
+
+ st->cstate = C0;
+ st->_errno = 0;
+
+ return ((void *) st);
+}
+
+/*
+ * Close; called from iconv_close()
+ */
+void _icv_close(_iconv_st * st) {
+ if (!st)
+ errno = EBADF;
+ else
+ free(st);
+}
+
+/*
+ * Actual conversion; called from iconv()
+ */
+
+size_t _icv_iconv(_iconv_st * st, char **inbuf, size_t *inbytesleft,
+ char ** outbuf, size_t *outbytesleft) {
+ int n;
+ if (st == NULL) {
+ errno = EBADF;
+ return ((size_t) -1);
+ }
+
+ if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
+ st->cstate = C0;
+ st->_errno = 0;
+ return ((size_t) 0);
+ }
+
+ errno = st->_errno = 0;
+
+ while (*inbytesleft > 0 && *outbytesleft > 0) {
+ switch (st->cstate) {
+ case C0:
+ if (**inbuf & MSB) { /* big5 charactor */
+ st->keepc[0] = (**inbuf);
+ st->cstate = C1;
+ } else { /* ASCII */
+ **outbuf = **inbuf;
+ (*outbuf)++;
+ (*outbytesleft)--;
+ }
+ break;
+ case C1: /* Big5 charactor 2nd byte */
+ if (big5_2nd_byte(**inbuf) == 0) {
+ st->keepc[1] = (**inbuf);
+ n = big5p_to_hkscs(st->keepc, *outbuf, *outbytesleft);
+ if (n > 0) {
+ (*outbuf) += n;
+ (*outbytesleft) -= n;
+
+ st->cstate = C0;
+ } else {
+ st->_errno = errno = E2BIG;
+ }
+ } else { /* illegal input */
+ st->_errno = errno =EILSEQ;
+ }
+ break;
+ default:
+ st->_errno = errno = EILSEQ;
+ st->cstate = C0;
+ break;
+ }
+
+ if (st->_errno)
+ break;
+
+ (*inbuf) ++;
+ (*inbytesleft)--;
+ }
+
+ if (errno) return ((size_t) -1);
+
+ if (*inbytesleft == 0 && st->cstate != C0) {
+ errno = EINVAL;
+ return ((size_t) -1);
+ }
+
+ if (*inbytesleft > 0 && *outbytesleft == 0) {
+ errno = E2BIG;
+ return (size_t)-1;
+ }
+
+ return (size_t)(*inbytesleft);
+}
+
+/*
+ * Test whether inbuf is a valid character for
+ * 2nd byte of BIG5 charactor:
+ * Return: 0 --- valid BIG5 2nd byte
+ * 1 --- invalid BIG5 2nd byte
+ */
+int big5_2nd_byte(inbuf)
+char inbuf;
+{
+ unsigned int buf = (unsigned int)(inbuf & ONEBYTE);
+
+ if ((buf >= 0x40) && (buf <= 0xfe))
+ return 0;
+ return 1;
+}
+
+/*
+ * big5p_to_gbk: Convert Big5 to gbk.
+ * Return: >0 --- converted with enough space in output buffer
+ * =0 --- no space in outbuf
+ */
+
+int big5p_to_hkscs(char keepc[], char *buf, size_t buflen) {
+
+ unsigned long gbk_val;
+ int index;
+ unsigned long big5_val;
+
+ if (buflen < 2) {
+ errno = E2BIG;
+ return 0;
+ }
+
+ big5_val = ((keepc[0] & ONEBYTE) << 8) + (keepc[1] & ONEBYTE);
+ index = binsearch(big5_val, big5p_hkscs_tab, BIG5MAX);
+ if (index >= 0) {
+ gbk_val = big5p_hkscs_tab[index].value;
+ *buf = (gbk_val >> 8) & ONEBYTE;
+ *(buf + 1) = gbk_val & ONEBYTE;
+ } else
+ *buf = *(buf + 1) = (char)NON_ID_CHAR;
+ return 2;
+}
+
+/*
+ * binsearch()
+ */
+int binsearch(unsigned long x, table_t table[], int n) {
+ int low, high, mid;
+
+ low = 0;
+ high = n - 1;
+ while (low <= high) {
+ mid = (low + high) >> 1;
+ if (x < table[mid].key)
+ high = mid - 1;
+ else if (x > table[mid].key)
+ low = mid + 1;
+ else
+ return mid;
+ }
+ return -1;
+}