1/* Test whether case matters for a Unicode string.
2   Copyright (C) 2009-2010 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2009.
4
5   This program is free software: you can redistribute it and/or modify it
6   under the terms of the GNU Lesser General Public License as published
7   by the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18int
19FUNC (const UNIT *s, size_t n, const char *iso639_language,
20      bool *resultp)
21{
22  UNIT normsbuf[2048 / sizeof (UNIT)];
23  UNIT *norms;
24  size_t norms_length;
25  UNIT mappedbuf[2048 / sizeof (UNIT)];
26  UNIT *mapped_toupper;
27  UNIT *mapped_tolower;
28  UNIT *mapped_totitle;
29  size_t mapped_length;
30
31  /* Apply canonical decomposition to S.  */
32  norms_length = sizeof (normsbuf) / sizeof (UNIT);
33  norms = U_NORMALIZE (UNINORM_NFD, s, n, normsbuf, &norms_length);
34  if (norms == NULL)
35    /* errno is set here.  */
36    return -1;
37
38  mapped_length = sizeof (mappedbuf) / sizeof (UNIT);
39
40  /* Apply toupper mapping.  */
41  mapped_toupper = U_TOUPPER (norms, norms_length, iso639_language, NULL,
42                              mappedbuf, &mapped_length);
43  if (mapped_toupper == NULL)
44    goto fail;
45
46  /* Compare.  */
47  if (!(mapped_length == norms_length
48        && U_CMP (mapped_toupper, norms, norms_length) == 0))
49    {
50      if (mapped_toupper != mappedbuf)
51        free (mapped_toupper);
52      goto yes;
53    }
54
55  /* Apply tolower mapping.  */
56  mapped_tolower = U_TOLOWER (norms, norms_length, iso639_language, NULL,
57                              mapped_toupper, &mapped_length);
58  if (mapped_tolower == NULL)
59    {
60      if (mapped_toupper != mappedbuf)
61        {
62          int saved_errno = errno;
63          free (mapped_toupper);
64          errno = saved_errno;
65        }
66      goto fail;
67    }
68
69  if (mapped_toupper != mapped_tolower && mapped_toupper != mappedbuf)
70    free (mapped_toupper);
71
72  /* Compare.  */
73  if (!(mapped_length == norms_length
74        && U_CMP (mapped_tolower, norms, norms_length) == 0))
75    {
76      if (mapped_tolower != mappedbuf)
77        free (mapped_tolower);
78      goto yes;
79    }
80
81  /* Apply totitle mapping.  */
82  mapped_totitle = U_TOTITLE (norms, norms_length, iso639_language, NULL,
83                              mapped_tolower, &mapped_length);
84  if (mapped_totitle == NULL)
85    {
86      if (mapped_tolower != mappedbuf)
87        {
88          int saved_errno = errno;
89          free (mapped_tolower);
90          errno = saved_errno;
91        }
92      goto fail;
93    }
94
95  if (mapped_tolower != mapped_totitle && mapped_tolower != mappedbuf)
96    free (mapped_tolower);
97
98  /* Compare.  */
99  if (!(mapped_length == norms_length
100        && U_CMP (mapped_totitle, norms, norms_length) == 0))
101    {
102      if (mapped_totitle != mappedbuf)
103        free (mapped_totitle);
104      goto yes;
105    }
106
107  if (mapped_totitle != mappedbuf)
108    free (mapped_totitle);
109  if (norms != normsbuf)
110    free (norms);
111  *resultp = false;
112  return 0;
113
114 yes:
115  if (norms != normsbuf)
116    free (norms);
117  *resultp = true;
118  return 0;
119
120 fail:
121  if (norms != normsbuf)
122    {
123      int saved_errno = errno;
124      free (norms);
125      errno = saved_errno;
126    }
127  return -1;
128}
129