xref: /freebsd/lib/libc/string/wcsxfrm.c (revision aa8d1268470ffd149ee631369ab7dc12e128465c)
1fd4f1dd9STim J. Robbins /*-
2d915a14eSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3d915a14eSPedro F. Giffuni  *
42a6abeebSBaptiste Daroussin  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
5fd4f1dd9STim J. Robbins  * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
6fd4f1dd9STim J. Robbins  *		at Electronni Visti IA, Kiev, Ukraine.
7fd4f1dd9STim J. Robbins  *			All rights reserved.
8fd4f1dd9STim J. Robbins  *
93c87aa1dSDavid Chisnall  * Copyright (c) 2011 The FreeBSD Foundation
103c87aa1dSDavid Chisnall  * All rights reserved.
113c87aa1dSDavid Chisnall  * Portions of this software were developed by David Chisnall
123c87aa1dSDavid Chisnall  * under sponsorship from the FreeBSD Foundation.
133c87aa1dSDavid Chisnall  *
14fd4f1dd9STim J. Robbins  * Redistribution and use in source and binary forms, with or without
15fd4f1dd9STim J. Robbins  * modification, are permitted provided that the following conditions
16fd4f1dd9STim J. Robbins  * are met:
17fd4f1dd9STim J. Robbins  * 1. Redistributions of source code must retain the above copyright
18fd4f1dd9STim J. Robbins  *    notice, this list of conditions and the following disclaimer.
19fd4f1dd9STim J. Robbins  * 2. Redistributions in binary form must reproduce the above copyright
20fd4f1dd9STim J. Robbins  *    notice, this list of conditions and the following disclaimer in the
21fd4f1dd9STim J. Robbins  *    documentation and/or other materials provided with the distribution.
22fd4f1dd9STim J. Robbins  *
23fd4f1dd9STim J. Robbins  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
24fd4f1dd9STim J. Robbins  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25fd4f1dd9STim J. Robbins  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26fd4f1dd9STim J. Robbins  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
27fd4f1dd9STim J. Robbins  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28fd4f1dd9STim J. Robbins  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29fd4f1dd9STim J. Robbins  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30fd4f1dd9STim J. Robbins  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31fd4f1dd9STim J. Robbins  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32fd4f1dd9STim J. Robbins  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33fd4f1dd9STim J. Robbins  * SUCH DAMAGE.
34fd4f1dd9STim J. Robbins  */
35fd4f1dd9STim J. Robbins 
36fd4f1dd9STim J. Robbins #include <sys/cdefs.h>
37fd4f1dd9STim J. Robbins __FBSDID("$FreeBSD$");
38fd4f1dd9STim J. Robbins 
39fd4f1dd9STim J. Robbins #include <stdlib.h>
40fd4f1dd9STim J. Robbins #include <string.h>
41fd4f1dd9STim J. Robbins #include <wchar.h>
42fd4f1dd9STim J. Robbins #include "collate.h"
43fd4f1dd9STim J. Robbins 
44fd4f1dd9STim J. Robbins size_t
453c87aa1dSDavid Chisnall wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale)
46fd4f1dd9STim J. Robbins {
47fd4f1dd9STim J. Robbins 	size_t slen;
483c87aa1dSDavid Chisnall 	FIX_LOCALE(locale);
493c87aa1dSDavid Chisnall 	struct xlocale_collate *table =
503c87aa1dSDavid Chisnall 		(struct xlocale_collate*)locale->components[XLC_COLLATE];
51fd4f1dd9STim J. Robbins 
52fd4f1dd9STim J. Robbins 	if (*src == L'\0') {
53fd4f1dd9STim J. Robbins 		if (len != 0)
54fd4f1dd9STim J. Robbins 			*dest = L'\0';
55fd4f1dd9STim J. Robbins 		return (0);
56fd4f1dd9STim J. Robbins 	}
57fd4f1dd9STim J. Robbins 
582a6abeebSBaptiste Daroussin 	if ((table->__collate_load_error) ||
592a6abeebSBaptiste Daroussin 	    ((slen = _collate_wxfrm(table, src, dest, len)) == (size_t)-1)) {
602a6abeebSBaptiste Daroussin 		goto error;
612a6abeebSBaptiste Daroussin 	}
622a6abeebSBaptiste Daroussin 
632a6abeebSBaptiste Daroussin 	/* Add null termination at the correct location. */
642a6abeebSBaptiste Daroussin 	if (len > slen) {
652a6abeebSBaptiste Daroussin 		dest[slen] = 0;
662a6abeebSBaptiste Daroussin 	} else if (len) {
672a6abeebSBaptiste Daroussin 		dest[len-1] = 0;
682a6abeebSBaptiste Daroussin 	}
692a6abeebSBaptiste Daroussin 
702a6abeebSBaptiste Daroussin 	return (slen);
712a6abeebSBaptiste Daroussin 
722a6abeebSBaptiste Daroussin error:
73fd4f1dd9STim J. Robbins 	slen = wcslen(src);
74fd4f1dd9STim J. Robbins 	if (slen < len)
752a6abeebSBaptiste Daroussin 		(void) wcscpy(dest, src);
76*aa8d1268SDimitry Andric 	else if (len > 0) {
772a6abeebSBaptiste Daroussin 		(void) wcsncpy(dest, src, len - 1);
78fd4f1dd9STim J. Robbins 		dest[len - 1] = L'\0';
79fd4f1dd9STim J. Robbins 	}
80fd4f1dd9STim J. Robbins 	return (slen);
81fd4f1dd9STim J. Robbins }
82fd4f1dd9STim J. Robbins 
833c87aa1dSDavid Chisnall size_t
843c87aa1dSDavid Chisnall wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
853c87aa1dSDavid Chisnall {
863c87aa1dSDavid Chisnall 	return wcsxfrm_l(dest, src, len, __get_locale());
873c87aa1dSDavid Chisnall }
88