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