xref: /illumos-gate/usr/src/lib/iconv_modules/utf-8/common/sb_to_utf8.c (revision 16d8656330ae5622ec32e5007f62145ebafdc50f)
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 2004 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  *
25  * This program assumes that all single byte coded characters will be either
26  * map to UTF-8 coded characters or illegal characters. Thus no replacement is
27  * assumed at the moment.
28  *
29  * This particular file is to cover conversions from various single byte
30  * codesets to UTF-8.
31  */
32 
33 
34 #include <stdlib.h>
35 #include <errno.h>
36 #include "sb_to_utf8.h"
37 
38 
39 void *
_icv_open()40 _icv_open()
41 {
42 	return((void *)MAGIC_NUMBER);
43 }
44 
45 
46 void
_icv_close(int * cd)47 _icv_close(int *cd)
48 {
49 	if (! cd || cd != (int *)MAGIC_NUMBER)
50 		errno = EBADF;
51 }
52 
53 
54 size_t
_icv_iconv(int * cd,char ** inbuf,size_t * inbufleft,char ** outbuf,size_t * outbufleft)55 _icv_iconv(int *cd, char **inbuf, size_t *inbufleft, char **outbuf,
56                 size_t *outbufleft)
57 {
58 	size_t ret_val = 0;
59 	unsigned char *ib;
60 	unsigned char *ob;
61 	unsigned char *ibtail;
62 	unsigned char *obtail;
63 
64 	if (cd != (int *)MAGIC_NUMBER) {
65 		errno = EBADF;
66 		return((size_t)-1);
67 	}
68 
69 	if (!inbuf || !(*inbuf))
70 		return((size_t)0);
71 
72 	ib = (unsigned char *)*inbuf;
73 	ob = (unsigned char *)*outbuf;
74 	ibtail = ib + *inbufleft;
75 	obtail = ob + *outbufleft;
76 
77 	while (ib < ibtail) {
78 		register int i;
79 		unsigned long u8;
80 		signed char sz;
81 
82 		u8 = (unsigned long)sb_u8_tbl[*ib].u8;
83 		sz = sb_u8_tbl[*ib].size;
84 
85 		if (sz == ICV_TYPE_ILLEGAL_CHAR) {
86 			errno = EILSEQ;
87 			ret_val = (size_t)-1;
88 			break;
89 		}
90 
91 		if ((u8 & ICV_UTF8_REPRESENTATION_ffff_mask) ==
92 		    ICV_UTF8_REPRESENTATION_fffe ||
93 		    (u8 & ICV_UTF8_REPRESENTATION_ffff_mask) ==
94 		    ICV_UTF8_REPRESENTATION_ffff ||
95 		    u8 > ICV_UTF8_REPRESENTATION_10fffd ||
96 		    (u8 >= ICV_UTF8_REPRESENTATION_d800 &&
97 		    u8 <= ICV_UTF8_REPRESENTATION_dfff) ||
98 		    (u8 >= ICV_UTF8_REPRESENTATION_fdd0 &&
99 		    u8 <= ICV_UTF8_REPRESENTATION_fdef)) {
100 			/* This should not happen, if sb_u8_tbl is right. */
101 			errno = EILSEQ;
102 			ret_val = (size_t)-1;
103 			break;
104 		}
105 
106 		if ((obtail - ob) < sz) {
107 			errno = E2BIG;
108 			ret_val = (size_t)-1;
109 			break;
110 		}
111 
112 		for (i = 1; i <= sz; i++)
113 			*ob++ = (unsigned int)((u8 >> ((sz - i) * 8)) & 0xff);
114 		ib++;
115 	}
116 
117 	*inbuf = (char *)ib;
118 	*inbufleft = ibtail - ib;
119 	*outbuf = (char *)ob;
120 	*outbufleft = obtail - ob;
121 
122 	return(ret_val);
123 }
124