xref: /freebsd/lib/libc/string/strxfrm.c (revision 559a218c9b257775fb249b67945fe4a05b7a6b9f)
158f0484fSRodney W. Grimes /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3d915a14eSPedro F. Giffuni  *
42a6abeebSBaptiste Daroussin  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
5a4d5d0cbSAndrey A. Chernov  * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
6a4d5d0cbSAndrey A. Chernov  *		at Electronni Visti IA, Kiev, Ukraine.
7a4d5d0cbSAndrey A. Chernov  *			All rights reserved.
858f0484fSRodney W. Grimes  *
93c87aa1dSDavid Chisnall  * Copyright (c) 2011 The FreeBSD Foundation
105b5fa75aSEd Maste  *
113c87aa1dSDavid Chisnall  * Portions of this software were developed by David Chisnall
123c87aa1dSDavid Chisnall  * under sponsorship from the FreeBSD Foundation.
133c87aa1dSDavid Chisnall  *
1458f0484fSRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
1558f0484fSRodney W. Grimes  * modification, are permitted provided that the following conditions
1658f0484fSRodney W. Grimes  * are met:
1758f0484fSRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
1858f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
1958f0484fSRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
2058f0484fSRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
2158f0484fSRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
2258f0484fSRodney W. Grimes  *
23a4d5d0cbSAndrey A. Chernov  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
2458f0484fSRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2558f0484fSRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26a4d5d0cbSAndrey A. Chernov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
2758f0484fSRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2858f0484fSRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2958f0484fSRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3058f0484fSRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3158f0484fSRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3258f0484fSRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3358f0484fSRodney W. Grimes  * SUCH DAMAGE.
3458f0484fSRodney W. Grimes  */
3558f0484fSRodney W. Grimes 
36a4d5d0cbSAndrey A. Chernov #include <stdlib.h>
3758f0484fSRodney W. Grimes #include <string.h>
382a6abeebSBaptiste Daroussin #include <errno.h>
392a6abeebSBaptiste Daroussin #include <wchar.h>
40a4d5d0cbSAndrey A. Chernov #include "collate.h"
4158f0484fSRodney W. Grimes 
4258f0484fSRodney W. Grimes size_t
433c87aa1dSDavid Chisnall strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t loc);
443c87aa1dSDavid Chisnall size_t
strxfrm(char * __restrict dest,const char * __restrict src,size_t len)4533f9b60eSRobert Drehmel strxfrm(char * __restrict dest, const char * __restrict src, size_t len)
4658f0484fSRodney W. Grimes {
473c87aa1dSDavid Chisnall 	return strxfrm_l(dest, src, len, __get_locale());
483c87aa1dSDavid Chisnall }
493c87aa1dSDavid Chisnall 
503c87aa1dSDavid Chisnall size_t
strxfrm_l(char * __restrict dest,const char * __restrict src,size_t len,locale_t locale)513c87aa1dSDavid Chisnall strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale)
523c87aa1dSDavid Chisnall {
53f0e6ee9fSAndrey A. Chernov 	size_t slen;
542a6abeebSBaptiste Daroussin 	size_t xlen;
552a6abeebSBaptiste Daroussin 	wchar_t *wcs = NULL;
562a6abeebSBaptiste Daroussin 
573c87aa1dSDavid Chisnall 	FIX_LOCALE(locale);
583c87aa1dSDavid Chisnall 	struct xlocale_collate *table =
593c87aa1dSDavid Chisnall 		(struct xlocale_collate*)locale->components[XLC_COLLATE];
60a4d5d0cbSAndrey A. Chernov 
61a4d5d0cbSAndrey A. Chernov 	if (!*src) {
62f0e6ee9fSAndrey A. Chernov 		if (len > 0)
63f0e6ee9fSAndrey A. Chernov 			*dest = '\0';
642a6abeebSBaptiste Daroussin 		return (0);
6558f0484fSRodney W. Grimes 	}
66a4d5d0cbSAndrey A. Chernov 
672a6abeebSBaptiste Daroussin 	/*
682a6abeebSBaptiste Daroussin 	 * The conversion from multibyte to wide character strings is
692a6abeebSBaptiste Daroussin 	 * strictly reducing (one byte of an mbs cannot expand to more
702a6abeebSBaptiste Daroussin 	 * than one wide character.)
712a6abeebSBaptiste Daroussin 	 */
722a6abeebSBaptiste Daroussin 	slen = strlen(src);
732a6abeebSBaptiste Daroussin 
743c87aa1dSDavid Chisnall 	if (table->__collate_load_error)
752a6abeebSBaptiste Daroussin 		goto error;
76a4d5d0cbSAndrey A. Chernov 
772a6abeebSBaptiste Daroussin 	if ((wcs = malloc((slen + 1) * sizeof (wchar_t))) == NULL)
782a6abeebSBaptiste Daroussin 		goto error;
79a4d5d0cbSAndrey A. Chernov 
802a6abeebSBaptiste Daroussin 	if (mbstowcs_l(wcs, src, slen + 1, locale) == (size_t)-1)
812a6abeebSBaptiste Daroussin 		goto error;
822a6abeebSBaptiste Daroussin 
832a6abeebSBaptiste Daroussin 	if ((xlen = _collate_sxfrm(table, wcs, dest, len)) == (size_t)-1)
842a6abeebSBaptiste Daroussin 		goto error;
852a6abeebSBaptiste Daroussin 
862a6abeebSBaptiste Daroussin 	free(wcs);
872a6abeebSBaptiste Daroussin 
882a6abeebSBaptiste Daroussin 	if (len > xlen) {
892a6abeebSBaptiste Daroussin 		dest[xlen] = 0;
902a6abeebSBaptiste Daroussin 	} else if (len) {
912a6abeebSBaptiste Daroussin 		dest[len-1] = 0;
922a6abeebSBaptiste Daroussin 	}
932a6abeebSBaptiste Daroussin 
942a6abeebSBaptiste Daroussin 	return (xlen);
952a6abeebSBaptiste Daroussin 
962a6abeebSBaptiste Daroussin error:
972a6abeebSBaptiste Daroussin 	/* errno should be set to ENOMEM if malloc failed */
982a6abeebSBaptiste Daroussin 	free(wcs);
99c71b5482SBaptiste Daroussin 	strlcpy(dest, src, len);
1002a6abeebSBaptiste Daroussin 
1012a6abeebSBaptiste Daroussin 	return (slen);
10258f0484fSRodney W. Grimes }
103