1/* Locale dependent transformation for case insensitive comparison of Unicode 2 strings. 3 Copyright (C) 2009-2010 Free Software Foundation, Inc. 4 Written by Bruno Haible <bruno@clisp.org>, 2009. 5 6 This program is free software: you can redistribute it and/or modify it 7 under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19char * 20FUNC (const UNIT *s, size_t n, const char *iso639_language, uninorm_t nf, 21 char *resultbuf, size_t *lengthp) 22{ 23 UNIT foldedsbuf[2048 / sizeof (UNIT)]; 24 UNIT *foldeds; 25 size_t foldeds_length; 26 char convsbuf[2048]; 27 char *convs; 28 size_t convs_length; 29 char *result; 30 31 /* Casefold and normalize the Unicode string. */ 32 foldeds_length = sizeof (foldedsbuf) / sizeof (UNIT); 33 foldeds = U_CASEFOLD (s, n, iso639_language, nf, foldedsbuf, &foldeds_length); 34 if (foldeds == NULL) 35 /* errno is set here. */ 36 return NULL; 37 38 /* Convert it to locale encoding. */ 39 convs_length = sizeof (convsbuf) - 1; 40 convs = U_CONV_TO_ENCODING (locale_charset (), 41 iconveh_error, 42 foldeds, foldeds_length, 43 NULL, 44 convsbuf, &convs_length); 45 if (convs == NULL) 46 { 47 if (foldeds != foldedsbuf) 48 { 49 int saved_errno = errno; 50 free (foldeds); 51 errno = saved_errno; 52 } 53 return NULL; 54 } 55 56 if (foldeds != foldedsbuf) 57 free (foldeds); 58 59 /* Ensure one more byte is available. */ 60 if (convs != convsbuf) 61 { 62 char *memory = (char *) realloc (convs, convs_length + 1); 63 if (memory == NULL) 64 { 65 free (convs); 66 errno = ENOMEM; 67 return NULL; 68 } 69 convs = memory; 70 } 71 72 /* Apply locale dependent transformations for comparison. */ 73 result = memxfrm (convs, convs_length, resultbuf, lengthp); 74 if (result == NULL) 75 { 76 if (convs != convsbuf) 77 { 78 int saved_errno = errno; 79 free (convs); 80 errno = saved_errno; 81 } 82 return NULL; 83 } 84 85 if (convs != convsbuf) 86 free (convs); 87 return result; 88} 89