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 usr/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 usr/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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /*
30 * Some wchar support functions used by this library.
31 * Mostlly just wrappers that call sys/u8_textprep.h
32 * functions: uconv_u8tou16, uconv_u16tou8.
33 */
34
35 #include <sys/types.h>
36 #include <sys/u8_textprep.h>
37 #include <string.h>
38
39 #include "ndr_wchar.h"
40
41 /*
42 * When we just want lengths, we need an output buffer to pass to the
43 * uconv_... functions. Nothing ever reads this output, so we can
44 * use shared space for the unwanted output.
45 */
46 static uint16_t junk_wcs[NDR_STRING_MAX];
47 static char junk_mbs[NDR_MB_CUR_MAX * NDR_STRING_MAX];
48
49 static size_t
50 ndr__mbstowcs_x(uint16_t *, const char *, size_t, int);
51
52 /*
53 * Like mbstowcs(3C), but with UCS-2 wchar_t
54 */
55 size_t
ndr__mbstowcs(uint16_t * wcs,const char * mbs,size_t nwchars)56 ndr__mbstowcs(uint16_t *wcs, const char *mbs, size_t nwchars)
57 {
58 return (ndr__mbstowcs_x(wcs, mbs, nwchars,
59 UCONV_OUT_SYSTEM_ENDIAN));
60 }
61
62 /*
63 * Like above, but put UCS-2 little-endian.
64 */
65 size_t
ndr__mbstowcs_le(uint16_t * wcs,const char * mbs,size_t nwchars)66 ndr__mbstowcs_le(uint16_t *wcs, const char *mbs, size_t nwchars)
67 {
68 return (ndr__mbstowcs_x(wcs, mbs, nwchars,
69 UCONV_OUT_LITTLE_ENDIAN));
70 }
71
72 /*
73 * Like mbstowcs(3C), but with UCS-2 wchar_t, and
74 * one extra arg for the byte order flags.
75 */
76 static size_t
ndr__mbstowcs_x(uint16_t * wcs,const char * mbs,size_t nwchars,int flags)77 ndr__mbstowcs_x(uint16_t *wcs, const char *mbs, size_t nwchars, int flags)
78 {
79 size_t obytes, mbslen, wcslen;
80 int err;
81
82 /* NULL or empty input is allowed. */
83 if (mbs == NULL || *mbs == '\0') {
84 if (wcs != NULL && nwchars > 0)
85 *wcs = 0;
86 return (0);
87 }
88
89 /*
90 * If wcs == NULL, caller just wants the length.
91 * Convert into some throw-away space.
92 */
93 obytes = nwchars * 2;
94 if (wcs == NULL) {
95 if (obytes > sizeof (junk_wcs))
96 return ((size_t)-1);
97 wcs = junk_wcs;
98 }
99
100 mbslen = strlen(mbs);
101 wcslen = nwchars;
102 err = uconv_u8tou16((const uchar_t *)mbs, &mbslen,
103 wcs, &wcslen, flags);
104 if (err != 0)
105 return ((size_t)-1);
106
107 if (wcslen < nwchars)
108 wcs[wcslen] = 0;
109
110 return (wcslen);
111 }
112
113 /*
114 * Like wcstombs(3C), but with UCS-2 wchar_t.
115 */
116 size_t
ndr__wcstombs(char * mbs,const uint16_t * wcs,size_t nbytes)117 ndr__wcstombs(char *mbs, const uint16_t *wcs, size_t nbytes)
118 {
119 size_t mbslen, wcslen;
120 int err;
121
122 /* NULL or empty input is allowed. */
123 if (wcs == NULL || *wcs == 0) {
124 if (mbs != NULL && nbytes > 0)
125 *mbs = '\0';
126 return (0);
127 }
128
129 /*
130 * If mbs == NULL, caller just wants the length.
131 * Convert into some throw-away space.
132 */
133 if (mbs == NULL) {
134 if (nbytes > sizeof (junk_mbs))
135 return ((size_t)-1);
136 mbs = junk_mbs;
137 }
138
139 wcslen = ndr__wcslen(wcs);
140 mbslen = nbytes;
141 err = uconv_u16tou8(wcs, &wcslen,
142 (uchar_t *)mbs, &mbslen, UCONV_IN_SYSTEM_ENDIAN);
143 if (err != 0)
144 return ((size_t)-1);
145
146 if (mbslen < nbytes)
147 mbs[mbslen] = '\0';
148
149 return (mbslen);
150 }
151
152 /*
153 * Like wcslen(3C), but with UCS-2 wchar_t.
154 */
155 size_t
ndr__wcslen(const uint16_t * wc)156 ndr__wcslen(const uint16_t *wc)
157 {
158 size_t len = 0;
159 while (*wc++)
160 len++;
161 return (len);
162 }
163