1 /* 2 * Copyright 2013 Garrett D'Amore <garrett@damore.org> 3 * Copyright 2010 Nexenta Systems, Inc. All rights reserved. 4 * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua> 5 * at Electronni Visti IA, Kiev, Ukraine. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #include "lint.h" 31 #include <stdlib.h> 32 #include <string.h> 33 #include <errno.h> 34 #include <wchar.h> 35 #include <assert.h> 36 #include <xlocale.h> 37 #include "collate.h" 38 39 size_t 40 strxfrm_l(char *_RESTRICT_KYWD xf, const char *_RESTRICT_KYWD src, 41 size_t dlen, locale_t loc) 42 { 43 size_t slen; 44 size_t xlen; 45 wchar_t *wcs = NULL; 46 47 if (!*src) { 48 if (dlen > 0) 49 *xf = '\0'; 50 return (0); 51 } 52 53 /* 54 * The conversion from multibyte to wide character strings is 55 * strictly reducing (one byte of an mbs cannot expand to more 56 * than one wide character.) 57 */ 58 slen = strlen(src); 59 60 if (loc->collate->lc_is_posix) 61 goto error; 62 63 if ((wcs = malloc((slen + 1) * sizeof (wchar_t))) == NULL) 64 goto error; 65 66 if (mbstowcs_l(wcs, src, slen + 1, loc) == (size_t)-1) 67 goto error; 68 69 if ((xlen = _collate_sxfrm(wcs, xf, dlen, loc)) == (size_t)-1) 70 goto error; 71 72 if (wcs) 73 free(wcs); 74 75 if (dlen > xlen) { 76 xf[xlen] = 0; 77 } else if (dlen) { 78 xf[dlen-1] = 0; 79 } 80 81 return (xlen); 82 83 error: 84 /* errno should be set to ENOMEM if malloc failed */ 85 if (wcs) 86 free(wcs); 87 (void) strlcpy(xf, src, dlen); 88 89 return (slen); 90 } 91 92 size_t 93 strxfrm(char *_RESTRICT_KYWD xf, const char *_RESTRICT_KYWD src, size_t dlen) 94 { 95 return (strxfrm_l(xf, src, dlen, uselocale(NULL))); 96 }