uchar C++ tests: Fix build error on FreeBSD 12.
[gnulib.git] / lib / unicase / u-ct-casefold.h
blob7d9307c517c0dcbe8031d3ea8146665bfd9a541d
1 /* Casefolding mapping for Unicode substrings (locale dependent).
2 Copyright (C) 2009-2020 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2009.
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.
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.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
18 UNIT *
19 FUNC (const UNIT *s, size_t n,
20 casing_prefix_context_t prefix_context,
21 casing_suffix_context_t suffix_context,
22 const char *iso639_language,
23 uninorm_t nf,
24 UNIT *resultbuf, size_t *lengthp)
26 /* Implement the three definitions of caseless matching, as described in
27 Unicode 5.0, section "Default caseless matching":
28 - If no normalization is requested, simply apply the casefolding.
29 X -> toCasefold(X).
30 - If canonical normalization is requested, apply it, and apply an NFD
31 before.
32 X -> NFD(toCasefold(NFD(X))).
33 - If compatibility normalization is requested, apply it twice, apply
34 the normalization after each, and apply an NFD before:
35 X -> NFKD(toCasefold(NFKD(toCasefold(NFD(X))))). */
36 if (nf == NULL)
37 /* X -> toCasefold(X) */
38 return U_CASEMAP (s, n, prefix_context, suffix_context, iso639_language,
39 uc_tocasefold, offsetof (struct special_casing_rule, casefold[0]),
40 NULL,
41 resultbuf, lengthp);
42 else
44 uninorm_t nfd = uninorm_decomposing_form (nf);
45 /* X -> nf(toCasefold(NFD(X))) or
46 X -> nf(toCasefold(nfd(toCasefold(NFD(X))))) */
47 int repeat = (uninorm_is_compat_decomposing (nf) ? 2 : 1);
48 UNIT tmpbuf1[2048 / sizeof (UNIT)];
49 UNIT tmpbuf2[2048 / sizeof (UNIT)];
50 UNIT *tmp1;
51 size_t tmp1_length;
52 UNIT *tmp2;
53 size_t tmp2_length;
55 tmp1_length = sizeof (tmpbuf1) / sizeof (UNIT);
56 tmp1 = U_NORMALIZE (UNINORM_NFD, s, n, tmpbuf1, &tmp1_length);
57 if (tmp1 == NULL)
58 /* errno is set here. */
59 return NULL;
63 tmp2_length = sizeof (tmpbuf2) / sizeof (UNIT);
64 tmp2 = U_CASEMAP (tmp1, tmp1_length,
65 prefix_context, suffix_context, iso639_language,
66 uc_tocasefold, offsetof (struct special_casing_rule, casefold[0]),
67 NULL,
68 tmpbuf2, &tmp2_length);
69 if (tmp2 == NULL)
71 int saved_errno = errno;
72 if (tmp1 != tmpbuf1)
73 free (tmp1);
74 errno = saved_errno;
75 return NULL;
78 if (tmp1 != tmpbuf1)
79 free (tmp1);
81 if (repeat > 1)
83 tmp1_length = sizeof (tmpbuf1) / sizeof (UNIT);
84 tmp1 = U_NORMALIZE (nfd, tmp2, tmp2_length,
85 tmpbuf1, &tmp1_length);
87 else
88 /* Last run through this loop. */
89 tmp1 = U_NORMALIZE (nf, tmp2, tmp2_length,
90 resultbuf, lengthp);
91 if (tmp1 == NULL)
93 int saved_errno = errno;
94 if (tmp2 != tmpbuf2)
95 free (tmp2);
96 errno = saved_errno;
97 return NULL;
100 if (tmp2 != tmpbuf2)
101 free (tmp2);
103 while (--repeat > 0);
105 return tmp1;