1*3299f39fSGordon Ross /*
2*3299f39fSGordon Ross  * CDDL HEADER START
3*3299f39fSGordon Ross  *
4*3299f39fSGordon Ross  * The contents of this file are subject to the terms of the
5*3299f39fSGordon Ross  * Common Development and Distribution License (the "License").
6*3299f39fSGordon Ross  * You may not use this file except in compliance with the License.
7*3299f39fSGordon Ross  *
8*3299f39fSGordon Ross  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*3299f39fSGordon Ross  * or http://www.opensolaris.org/os/licensing.
10*3299f39fSGordon Ross  * See the License for the specific language governing permissions
11*3299f39fSGordon Ross  * and limitations under the License.
12*3299f39fSGordon Ross  *
13*3299f39fSGordon Ross  * When distributing Covered Code, include this CDDL HEADER in each
14*3299f39fSGordon Ross  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*3299f39fSGordon Ross  * If applicable, add the following below this CDDL HEADER, with the
16*3299f39fSGordon Ross  * fields enclosed by brackets "[]" replaced with your own identifying
17*3299f39fSGordon Ross  * information: Portions Copyright [yyyy] [name of copyright owner]
18*3299f39fSGordon Ross  *
19*3299f39fSGordon Ross  * CDDL HEADER END
20*3299f39fSGordon Ross  */
21*3299f39fSGordon Ross 
22*3299f39fSGordon Ross /*
23*3299f39fSGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*3299f39fSGordon Ross  * Use is subject to license terms.
25*3299f39fSGordon Ross  *
26*3299f39fSGordon Ross  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
27*3299f39fSGordon Ross  */
28*3299f39fSGordon Ross 
29*3299f39fSGordon Ross /*
30*3299f39fSGordon Ross  * Some wchar support functions used by this library.
31*3299f39fSGordon Ross  * Mostlly just wrappers that call sys/u8_textprep.h
32*3299f39fSGordon Ross  * functions: uconv_u8tou16, uconv_u16tou8.
33*3299f39fSGordon Ross  */
34*3299f39fSGordon Ross 
35*3299f39fSGordon Ross #include <sys/types.h>
36*3299f39fSGordon Ross #include <sys/u8_textprep.h>
37*3299f39fSGordon Ross #include <string.h>
38*3299f39fSGordon Ross 
39*3299f39fSGordon Ross #include "ndr_wchar.h"
40*3299f39fSGordon Ross 
41*3299f39fSGordon Ross /*
42*3299f39fSGordon Ross  * When we just want lengths, we need an output buffer to pass to the
43*3299f39fSGordon Ross  * uconv_... functions.  Nothing ever reads this output, so we can
44*3299f39fSGordon Ross  * use shared space for the unwanted output.
45*3299f39fSGordon Ross  */
46*3299f39fSGordon Ross static uint16_t junk_wcs[NDR_STRING_MAX];
47*3299f39fSGordon Ross static char junk_mbs[NDR_MB_CUR_MAX * NDR_STRING_MAX];
48*3299f39fSGordon Ross 
49*3299f39fSGordon Ross static size_t
50*3299f39fSGordon Ross ndr__mbstowcs_x(uint16_t *, const char *, size_t, int);
51*3299f39fSGordon Ross 
52*3299f39fSGordon Ross /*
53*3299f39fSGordon Ross  * Like mbstowcs(3C), but with UCS-2 wchar_t
54*3299f39fSGordon Ross  */
55*3299f39fSGordon Ross size_t
ndr__mbstowcs(uint16_t * wcs,const char * mbs,size_t nwchars)56*3299f39fSGordon Ross ndr__mbstowcs(uint16_t *wcs, const char *mbs, size_t nwchars)
57*3299f39fSGordon Ross {
58*3299f39fSGordon Ross 	return (ndr__mbstowcs_x(wcs, mbs, nwchars,
59*3299f39fSGordon Ross 	    UCONV_OUT_SYSTEM_ENDIAN));
60*3299f39fSGordon Ross }
61*3299f39fSGordon Ross 
62*3299f39fSGordon Ross /*
63*3299f39fSGordon Ross  * Like above, but put UCS-2 little-endian.
64*3299f39fSGordon Ross  */
65*3299f39fSGordon Ross size_t
ndr__mbstowcs_le(uint16_t * wcs,const char * mbs,size_t nwchars)66*3299f39fSGordon Ross ndr__mbstowcs_le(uint16_t *wcs, const char *mbs, size_t nwchars)
67*3299f39fSGordon Ross {
68*3299f39fSGordon Ross 	return (ndr__mbstowcs_x(wcs, mbs, nwchars,
69*3299f39fSGordon Ross 	    UCONV_OUT_LITTLE_ENDIAN));
70*3299f39fSGordon Ross }
71*3299f39fSGordon Ross 
72*3299f39fSGordon Ross /*
73*3299f39fSGordon Ross  * Like mbstowcs(3C), but with UCS-2 wchar_t, and
74*3299f39fSGordon Ross  * one extra arg for the byte order flags.
75*3299f39fSGordon Ross  */
76*3299f39fSGordon Ross static size_t
ndr__mbstowcs_x(uint16_t * wcs,const char * mbs,size_t nwchars,int flags)77*3299f39fSGordon Ross ndr__mbstowcs_x(uint16_t *wcs, const char *mbs, size_t nwchars, int flags)
78*3299f39fSGordon Ross {
79*3299f39fSGordon Ross 	size_t obytes, mbslen, wcslen;
80*3299f39fSGordon Ross 	int err;
81*3299f39fSGordon Ross 
82*3299f39fSGordon Ross 	/* NULL or empty input is allowed. */
83*3299f39fSGordon Ross 	if (mbs == NULL || *mbs == '\0') {
84*3299f39fSGordon Ross 		if (wcs != NULL && nwchars > 0)
85*3299f39fSGordon Ross 			*wcs = 0;
86*3299f39fSGordon Ross 		return (0);
87*3299f39fSGordon Ross 	}
88*3299f39fSGordon Ross 
89*3299f39fSGordon Ross 	/*
90*3299f39fSGordon Ross 	 * If wcs == NULL, caller just wants the length.
91*3299f39fSGordon Ross 	 * Convert into some throw-away space.
92*3299f39fSGordon Ross 	 */
93*3299f39fSGordon Ross 	obytes = nwchars * 2;
94*3299f39fSGordon Ross 	if (wcs == NULL) {
95*3299f39fSGordon Ross 		if (obytes > sizeof (junk_wcs))
96*3299f39fSGordon Ross 			return ((size_t)-1);
97*3299f39fSGordon Ross 		wcs = junk_wcs;
98*3299f39fSGordon Ross 	}
99*3299f39fSGordon Ross 
100*3299f39fSGordon Ross 	mbslen = strlen(mbs);
101*3299f39fSGordon Ross 	wcslen = nwchars;
102*3299f39fSGordon Ross 	err = uconv_u8tou16((const uchar_t *)mbs, &mbslen,
103*3299f39fSGordon Ross 	    wcs, &wcslen, flags);
104*3299f39fSGordon Ross 	if (err != 0)
105*3299f39fSGordon Ross 		return ((size_t)-1);
106*3299f39fSGordon Ross 
107*3299f39fSGordon Ross 	if (wcslen < nwchars)
108*3299f39fSGordon Ross 		wcs[wcslen] = 0;
109*3299f39fSGordon Ross 
110*3299f39fSGordon Ross 	return (wcslen);
111*3299f39fSGordon Ross }
112*3299f39fSGordon Ross 
113*3299f39fSGordon Ross /*
114*3299f39fSGordon Ross  * Like wcstombs(3C), but with UCS-2 wchar_t.
115*3299f39fSGordon Ross  */
116*3299f39fSGordon Ross size_t
ndr__wcstombs(char * mbs,const uint16_t * wcs,size_t nbytes)117*3299f39fSGordon Ross ndr__wcstombs(char *mbs, const uint16_t *wcs, size_t nbytes)
118*3299f39fSGordon Ross {
119*3299f39fSGordon Ross 	size_t mbslen, wcslen;
120*3299f39fSGordon Ross 	int err;
121*3299f39fSGordon Ross 
122*3299f39fSGordon Ross 	/* NULL or empty input is allowed. */
123*3299f39fSGordon Ross 	if (wcs == NULL || *wcs == 0) {
124*3299f39fSGordon Ross 		if (mbs != NULL && nbytes > 0)
125*3299f39fSGordon Ross 			*mbs = '\0';
126*3299f39fSGordon Ross 		return (0);
127*3299f39fSGordon Ross 	}
128*3299f39fSGordon Ross 
129*3299f39fSGordon Ross 	/*
130*3299f39fSGordon Ross 	 * If mbs == NULL, caller just wants the length.
131*3299f39fSGordon Ross 	 * Convert into some throw-away space.
132*3299f39fSGordon Ross 	 */
133*3299f39fSGordon Ross 	if (mbs == NULL) {
134*3299f39fSGordon Ross 		if (nbytes > sizeof (junk_mbs))
135*3299f39fSGordon Ross 			return ((size_t)-1);
136*3299f39fSGordon Ross 		mbs = junk_mbs;
137*3299f39fSGordon Ross 	}
138*3299f39fSGordon Ross 
139*3299f39fSGordon Ross 	wcslen = ndr__wcslen(wcs);
140*3299f39fSGordon Ross 	mbslen = nbytes;
141*3299f39fSGordon Ross 	err = uconv_u16tou8(wcs, &wcslen,
142*3299f39fSGordon Ross 	    (uchar_t *)mbs, &mbslen, UCONV_IN_SYSTEM_ENDIAN);
143*3299f39fSGordon Ross 	if (err != 0)
144*3299f39fSGordon Ross 		return ((size_t)-1);
145*3299f39fSGordon Ross 
146*3299f39fSGordon Ross 	if (mbslen < nbytes)
147*3299f39fSGordon Ross 		mbs[mbslen] = '\0';
148*3299f39fSGordon Ross 
149*3299f39fSGordon Ross 	return (mbslen);
150*3299f39fSGordon Ross }
151*3299f39fSGordon Ross 
152*3299f39fSGordon Ross /*
153*3299f39fSGordon Ross  * Like wcslen(3C), but with UCS-2 wchar_t.
154*3299f39fSGordon Ross  */
155*3299f39fSGordon Ross size_t
ndr__wcslen(const uint16_t * wc)156*3299f39fSGordon Ross ndr__wcslen(const uint16_t *wc)
157*3299f39fSGordon Ross {
158*3299f39fSGordon Ross 	size_t len = 0;
159*3299f39fSGordon Ross 	while (*wc++)
160*3299f39fSGordon Ross 		len++;
161*3299f39fSGordon Ross 	return (len);
162*3299f39fSGordon Ross }
163