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