da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER START
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The contents of this file are subject to the terms of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Common Development and Distribution License (the "License").
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You may not use this file except in compliance with the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * or http://www.opensolaris.org/os/licensing.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * See the License for the specific language governing permissions
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and limitations under the License.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * When distributing Covered Code, include this CDDL HEADER in each
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If applicable, add the following below this CDDL HEADER, with the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fields enclosed by brackets "[]" replaced with your own identifying
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * information: Portions Copyright [yyyy] [name of copyright owner]
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * CDDL HEADER END
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Use is subject to license terms.
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross *
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Multibyte/wide-char conversion routines. Wide-char encoding provides
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * a fixed size character encoding that maps to the Unicode 16-bit
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * (UCS-2) character set standard. Multibyte or UCS transformation
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * format (UTF) encoding is a variable length character encoding scheme
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * that s compatible with existing ASCII characters and guarantees that
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the resultant strings do not contain embedded null characters. Both
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * types of encoding provide a null terminator: single byte for UTF-8
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * and a wide-char null for Unicode. See RFC 2044.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The table below illustrates the UTF-8 encoding scheme. The letter x
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * indicates bits available for encoding the character value.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UCS-2 UTF-8 octet sequence (binary)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0x0000-0x007F 0xxxxxxx
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0x0080-0x07FF 110xxxxx 10xxxxxx
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 0x0800-0xFFFF 1110xxxx 10xxxxxx 10xxxxxx
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * RFC 2044
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UTF-8,a transformation format of UNICODE and ISO 10646
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * F. Yergeau
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Alis Technologies
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * October 1996
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross#if defined(_KERNEL) || defined(_FAKE_KERNEL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/types.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <sys/sunddi.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdio.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <stdlib.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <assert.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <strings.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#endif
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw#include <smbsrv/string.h>
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mbstowcs
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The mbstowcs() function converts a multibyte character string
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mbstring into a wide character string wcstring. No more than
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * nwchars wide characters are stored. A terminating null wide
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * character is appended if there is room.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the number of wide characters converted, not counting
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * any terminating null wide character. Returns -1 if an invalid
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * multibyte character is encountered.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsize_t
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_mbstowcs(smb_wchar_t *wcstring, const char *mbstring, size_t nwchars)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int len;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t *start = wcstring;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (nwchars--) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown len = smb_mbtowc(wcstring, mbstring, MTS_MB_CHAR_MAX);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (len < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *wcstring = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return ((size_t)-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*mbstring == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ++wcstring;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbstring += len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (wcstring - start);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mbtowc
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The mbtowc() function converts a multibyte character mbchar into
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * a wide character and stores the result in the object pointed to
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * by wcharp. Up to nbytes bytes are examined.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If mbchar is NULL, mbtowc() returns zero to indicate that shift
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * states are not supported. Shift states are used to switch between
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * representation modes using reserved bytes to signal shifting
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * without them being interpreted as characters. If mbchar is null
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * mbtowc should return non-zero if the current locale requires shift
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * states. Otherwise it should be return 0.
55bf511df53aad0fdb7eb3fa349f0308cc05234cas *
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * If mbchar is non-null, returns the number of bytes processed in
55bf511df53aad0fdb7eb3fa349f0308cc05234cas * mbchar. If mbchar is invalid, returns -1.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint /*ARGSUSED*/
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_mbtowc(smb_wchar_t *wcharp, const char *mbchar, size_t nbytes)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char mbyte;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t wide_char;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int count;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int bytes_left;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (mbchar == NULL)
55bf511df53aad0fdb7eb3fa349f0308cc05234cas return (0); /* no shift states */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* 0xxxxxxx -> 1 byte ASCII encoding */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (((mbyte = *mbchar++) & 0x80) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (wcharp)
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown *wcharp = (smb_wchar_t)mbyte;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (mbyte ? 1 : 0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /* 10xxxxxx -> invalid first byte */
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if ((mbyte & 0x40) == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char = mbyte;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((mbyte & 0x20) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char &= 0x1f;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bytes_left = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else if ((mbyte & 0x10) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char &= 0x0f;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bytes_left = 2;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw } else {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw count = 1;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (bytes_left--) {
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (((mbyte = *mbchar++) & 0xc0) != 0x80)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw count++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char = (wide_char << 6) | (mbyte & 0x3f);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (wcharp)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *wcharp = wide_char;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (count);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wctomb
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The wctomb() function converts a wide character wchar into a multibyte
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * character and stores the result in mbchar. The object pointed to by
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mbchar must be large enough to accommodate the multibyte character.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the numberof bytes written to mbchar.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_wctomb(char *mbchar, smb_wchar_t wchar)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((wchar & ~0x7f) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbchar = (char)wchar;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if ((wchar & ~0x7ff) == 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbchar++ = (wchar >> 6) | 0xc0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbchar = (wchar & 0x3f) | 0x80;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (2);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbchar++ = (wchar >> 12) | 0xe0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbchar++ = ((wchar >> 6) & 0x3f) | 0x80;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbchar = (wchar & 0x3f) | 0x80;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (3);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * wcstombs
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * The wcstombs() function converts a wide character string wcstring
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * into a multibyte character string mbstring. Up to nbytes bytes are
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * stored in mbstring. Partial multibyte characters at the end of the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * string are not stored. The multibyte character string is null
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * terminated if there is room.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the number of bytes converted, not counting the terminating
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * null byte.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsize_t
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_wcstombs(char *mbstring, const smb_wchar_t *wcstring, size_t nbytes)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *start = mbstring;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown const smb_wchar_t *wcp = wcstring;
b819cea2f73f98c5662230cc9affc8cc84f77fcfGordon Ross smb_wchar_t wide_char = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char buf[4];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if ((mbstring == NULL) || (wcstring == NULL))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (0);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (nbytes > MTS_MB_CHAR_MAX) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char = *wcp++;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown len = smb_wctomb(mbstring, wide_char);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (wide_char == 0)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*LINTED E_PTRDIFF_OVERFLOW*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (mbstring - start);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbstring += len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nbytes -= len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (wide_char && nbytes) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char = *wcp++;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if ((len = smb_wctomb(buf, wide_char)) > nbytes) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbstring = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw break;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw bcopy(buf, mbstring, len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbstring += len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw nbytes -= len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*LINTED E_PTRDIFF_OVERFLOW*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (mbstring - start);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the number of bytes that would be written if the multi-
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * byte string mbs was converted to a wide character string, not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * counting the terminating null wide character.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsize_t
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_wcequiv_strlen(const char *mbs)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t wide_char;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t bytes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t len = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*mbs) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown bytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (bytes == ((size_t)-1))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return ((size_t)-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown len += sizeof (smb_wchar_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbs += bytes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the number of bytes that would be written if the multi-
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * byte string mbs was converted to a single byte character string,
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * not counting the terminating null character.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwsize_t
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_sbequiv_strlen(const char *mbs)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t wide_char;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t nbytes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw size_t len = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*mbs) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (nbytes == ((size_t)-1))
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return ((size_t)-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (wide_char & 0xFF00)
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown len += sizeof (smb_wchar_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw ++len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbs += nbytes;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (len);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * stombs
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Convert a regular null terminated string 'string' to a UTF-8 encoded
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * null terminated multi-byte string 'mbstring'. Only full converted
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * UTF-8 characters will be written 'mbstring'. If a character will not
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * fit within the remaining buffer space or 'mbstring' will overflow
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * max_mblen, the conversion process will be terminated and 'mbstring'
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * will be null terminated.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Returns the number of bytes written to 'mbstring', excluding the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * terminating null character.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If either mbstring or string is a null pointer, -1 is returned.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_stombs(char *mbstring, char *string, int max_mblen)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char *start = mbstring;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *p = (unsigned char *)string;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int space_left = max_mblen;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int len;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t wide_char;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw char buf[4];
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (!mbstring || !string)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*p && space_left > 2) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char = *p++;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown len = smb_wctomb(mbstring, wide_char);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbstring += len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw space_left -= len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (*p) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw wide_char = *p;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if ((len = smb_wctomb(buf, wide_char)) < 2) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbstring = *buf;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbstring += len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw space_left -= len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *mbstring = '\0';
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*LINTED E_PTRDIFF_OVERFLOW*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (mbstring - start);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw/*
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * mbstos
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Convert a null terminated multi-byte string 'mbstring' to a regular
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * null terminated string 'string'. A 1-byte character in 'mbstring'
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * maps to a 1-byte character in 'string'. A 2-byte character in
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * 'mbstring' will be mapped to 2-bytes, if the upper byte is non-null.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * Otherwise the upper byte null will be discarded to ensure that the
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * output stream does not contain embedded null characters.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If the input stream contains invalid multi-byte characters, a value
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * of -1 will be returned. Otherwise the length of 'string', excluding
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * the terminating null character, is returned.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw * If either mbstring or string is a null pointer, -1 is returned.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw */
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwint
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brownsmb_mbstos(char *string, const char *mbstring)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw{
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown smb_wchar_t wc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw unsigned char *start = (unsigned char *)string;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw int len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
55bf511df53aad0fdb7eb3fa349f0308cc05234cas if (string == NULL || mbstring == NULL)
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw while (*mbstring) {
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown if ((len = smb_mbtowc(&wc, mbstring, MTS_MB_CHAR_MAX)) < 0) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *string = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return (-1);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw if (wc & 0xFF00) {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*LINTED E_BAD_PTR_CAST_ALIGN*/
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown *((smb_wchar_t *)string) = wc;
bbf6f00c25b6a2bed23c35eac6d62998ecdb338cJordan Brown string += sizeof (smb_wchar_t);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw else
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw {
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *string = (unsigned char)wc;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw string++;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw mbstring += len;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw }
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw *string = 0;
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw /*LINTED E_PTRDIFF_OVERFLOW*/
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw return ((unsigned char *)string - start);
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amw}