xref: /freebsd/lib/libc/string/wcsxfrm.c (revision 2a6abeebef961038d455abfcfcda14c16aec5b52)
1fd4f1dd9STim J. Robbins /*-
2*2a6abeebSBaptiste Daroussin  * Copyright 2010 Nexenta Systems, Inc.  All rights reserved.
3fd4f1dd9STim J. Robbins  * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
4fd4f1dd9STim J. Robbins  *		at Electronni Visti IA, Kiev, Ukraine.
5fd4f1dd9STim J. Robbins  *			All rights reserved.
6fd4f1dd9STim J. Robbins  *
73c87aa1dSDavid Chisnall  * Copyright (c) 2011 The FreeBSD Foundation
83c87aa1dSDavid Chisnall  * All rights reserved.
93c87aa1dSDavid Chisnall  * Portions of this software were developed by David Chisnall
103c87aa1dSDavid Chisnall  * under sponsorship from the FreeBSD Foundation.
113c87aa1dSDavid Chisnall  *
12fd4f1dd9STim J. Robbins  * Redistribution and use in source and binary forms, with or without
13fd4f1dd9STim J. Robbins  * modification, are permitted provided that the following conditions
14fd4f1dd9STim J. Robbins  * are met:
15fd4f1dd9STim J. Robbins  * 1. Redistributions of source code must retain the above copyright
16fd4f1dd9STim J. Robbins  *    notice, this list of conditions and the following disclaimer.
17fd4f1dd9STim J. Robbins  * 2. Redistributions in binary form must reproduce the above copyright
18fd4f1dd9STim J. Robbins  *    notice, this list of conditions and the following disclaimer in the
19fd4f1dd9STim J. Robbins  *    documentation and/or other materials provided with the distribution.
20fd4f1dd9STim J. Robbins  *
21fd4f1dd9STim J. Robbins  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
22fd4f1dd9STim J. Robbins  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23fd4f1dd9STim J. Robbins  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24fd4f1dd9STim J. Robbins  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE
25fd4f1dd9STim J. Robbins  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26fd4f1dd9STim J. Robbins  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27fd4f1dd9STim J. Robbins  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28fd4f1dd9STim J. Robbins  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29fd4f1dd9STim J. Robbins  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30fd4f1dd9STim J. Robbins  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31fd4f1dd9STim J. Robbins  * SUCH DAMAGE.
32fd4f1dd9STim J. Robbins  */
33fd4f1dd9STim J. Robbins 
34fd4f1dd9STim J. Robbins #include <sys/cdefs.h>
35fd4f1dd9STim J. Robbins __FBSDID("$FreeBSD$");
36fd4f1dd9STim J. Robbins 
37fd4f1dd9STim J. Robbins #include <stdlib.h>
38fd4f1dd9STim J. Robbins #include <string.h>
39fd4f1dd9STim J. Robbins #include <wchar.h>
40fd4f1dd9STim J. Robbins #include "collate.h"
41fd4f1dd9STim J. Robbins 
42fd4f1dd9STim J. Robbins size_t
433c87aa1dSDavid Chisnall wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale)
44fd4f1dd9STim J. Robbins {
45fd4f1dd9STim J. Robbins 	size_t slen;
463c87aa1dSDavid Chisnall 	FIX_LOCALE(locale);
473c87aa1dSDavid Chisnall 	struct xlocale_collate *table =
483c87aa1dSDavid Chisnall 		(struct xlocale_collate*)locale->components[XLC_COLLATE];
49fd4f1dd9STim J. Robbins 
50fd4f1dd9STim J. Robbins 	if (*src == L'\0') {
51fd4f1dd9STim J. Robbins 		if (len != 0)
52fd4f1dd9STim J. Robbins 			*dest = L'\0';
53fd4f1dd9STim J. Robbins 		return (0);
54fd4f1dd9STim J. Robbins 	}
55fd4f1dd9STim J. Robbins 
56*2a6abeebSBaptiste Daroussin 	if ((table->__collate_load_error) ||
57*2a6abeebSBaptiste Daroussin 	    ((slen = _collate_wxfrm(table, src, dest, len)) == (size_t)-1)) {
58*2a6abeebSBaptiste Daroussin 		goto error;
59*2a6abeebSBaptiste Daroussin 	}
60*2a6abeebSBaptiste Daroussin 
61*2a6abeebSBaptiste Daroussin 	/* Add null termination at the correct location. */
62*2a6abeebSBaptiste Daroussin 	if (len > slen) {
63*2a6abeebSBaptiste Daroussin 		dest[slen] = 0;
64*2a6abeebSBaptiste Daroussin 	} else if (len) {
65*2a6abeebSBaptiste Daroussin 		dest[len-1] = 0;
66*2a6abeebSBaptiste Daroussin 	}
67*2a6abeebSBaptiste Daroussin 
68*2a6abeebSBaptiste Daroussin 	return (slen);
69*2a6abeebSBaptiste Daroussin 
70*2a6abeebSBaptiste Daroussin error:
71fd4f1dd9STim J. Robbins 	slen = wcslen(src);
72fd4f1dd9STim J. Robbins 	if (slen < len)
73*2a6abeebSBaptiste Daroussin 		(void) wcscpy(dest, src);
74fd4f1dd9STim J. Robbins 	else {
75*2a6abeebSBaptiste Daroussin 		(void) wcsncpy(dest, src, len - 1);
76fd4f1dd9STim J. Robbins 		dest[len - 1] = L'\0';
77fd4f1dd9STim J. Robbins 	}
78fd4f1dd9STim J. Robbins 	return (slen);
79fd4f1dd9STim J. Robbins }
80fd4f1dd9STim J. Robbins 
813c87aa1dSDavid Chisnall size_t
823c87aa1dSDavid Chisnall wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
833c87aa1dSDavid Chisnall {
843c87aa1dSDavid Chisnall 	return wcsxfrm_l(dest, src, len, __get_locale());
853c87aa1dSDavid Chisnall }
86