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 */
46static uint16_t junk_wcs[NDR_STRING_MAX];
47static char junk_mbs[NDR_MB_CUR_MAX * NDR_STRING_MAX];
48
49static size_t
50ndr__mbstowcs_x(uint16_t *, const char *, size_t, int);
51
52/*
53 * Like mbstowcs(3C), but with UCS-2 wchar_t
54 */
55size_t
56ndr__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 */
65size_t
66ndr__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 */
76static size_t
77ndr__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 */
116size_t
117ndr__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 */
155size_t
156ndr__wcslen(const uint16_t *wc)
157{
158	size_t len = 0;
159	while (*wc++)
160		len++;
161	return (len);
162}
163