maint: update copyright
[gnulib.git] / lib / unicase / u-casexfrm.h
1 /* Locale dependent transformation for case insensitive comparison of Unicode
2    strings.
3    Copyright (C) 2009-2014 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
19 char *
20 FUNC (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 = amemxfrm (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 }