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) 2008, by Sun Microsystems, Inc.
23 * All rights reserved.
24 */
25
26 #include <stdio.h>
27 #include <errno.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #define __NEED_VISCII_2_UNI__
31 #include <unicode_viscii.h> /* Unicode to viscii mapping table */
32 #include "common_defs.h"
33
34
35 typedef struct _icv_state {
36 char keepc[4]; /* maximum # byte of UCS code */
37 int _errno; /* internal errno */
38 } _iconv_st;
39
40
41
42 /*
43 * Open; called from iconv_open()
44 */
45 void *
_icv_open()46 _icv_open()
47 {
48 _iconv_st *st;
49
50 if ((st = (_iconv_st *)malloc(sizeof(_iconv_st))) == NULL) {
51 errno = ENOMEM;
52 return ((void *) -1);
53 }
54
55 st->_errno = 0;
56 return ((void *) st);
57 }
58
59
60 /*
61 * Close; called from iconv_close()
62 */
63 void
_icv_close(_iconv_st * st)64 _icv_close(_iconv_st *st)
65 {
66 if (!st)
67 errno = EBADF;
68 else
69 free(st);
70 }
71
72
73 /*
74 * Actual conversion; called from iconv()
75 */
76 size_t
_icv_iconv(_iconv_st * st,char ** inbuf,size_t * inbytesleft,char ** outbuf,size_t * outbytesleft)77 _icv_iconv(_iconv_st *st, char **inbuf, size_t *inbytesleft,
78 char **outbuf, size_t *outbytesleft)
79 {
80
81 #ifdef DEBUG
82 fprintf(stderr, "========== iconv(): viscii -->UTF-8 ==========\n");
83 #endif
84 if (st == NULL) {
85 errno = EBADF;
86 return ((size_t) -1);
87 }
88
89 if (inbuf == NULL || *inbuf == NULL) { /* Reset request. */
90 st->_errno = 0;
91 return ((size_t) 0);
92 }
93
94 st->_errno = 0; /* reset internal errno */
95 errno = 0; /* reset external errno */
96
97 /* convert viscii encoding to UTF-8 */
98 while (*inbytesleft > 0 && *outbytesleft > 0) {
99 unsigned long uni = 0;
100
101 viscii_2_uni((unsigned char*)*inbuf, &uni);
102 if (uni < 0x80) {
103 *(*outbuf)++ = (char)uni;
104 (*outbytesleft) -= 1;
105 } else if (uni >= 0x0080 && uni <= 0x07ff) {
106 if (*outbytesleft < 2 ) {
107 errno = E2BIG;
108 return((size_t)-1);
109 }
110 *(*outbuf)++ = (char)((uni >> 6) & 0x1f) | 0xc0;
111 *(*outbuf)++ = (char)(uni & 0x3f) | 0x80;
112 *outbytesleft -= 2;
113 } else if (uni >= 0x0800 && uni <= 0xffff) {
114 if (*outbytesleft < 3) {
115 errno = E2BIG;
116 return((size_t)-1);
117 }
118 *(*outbuf)++ = (char)((uni >> 12) & 0xf) | 0xe0;
119 *(*outbuf)++ = (char)((uni >>6) & 0x3f) | 0x80;
120 *(*outbuf)++ = (char)(uni & 0x3f) | 0x80;
121 *outbytesleft -= 3;
122 }
123
124 (*inbuf)++;
125 (*inbytesleft)--;
126
127 }
128
129 if ( *inbytesleft > 0 && *outbytesleft <= 0 ) {
130 errno = E2BIG;
131 return ((size_t)-1);
132 }
133
134 return ((size_t)(*inbytesleft));
135 }
136