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