fchmod-tests, fchmodat tests, lchmod tests: Add more tests.
[gnulib.git] / lib / unicase / u-suffix-context.h
blob33aacfa86739cdc7e178484e9fd7172a26d97184
1 /* Case-mapping context of suffix UTF-8/UTF-16/UTF-32 string.
2 Copyright (C) 2009-2021 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 casing_suffix_context_t
19 FUNC1 (const UNIT *s, size_t n)
21 return FUNC2 (s, n, unicase_empty_suffix_context);
24 casing_suffix_context_t
25 FUNC2 (const UNIT *s, size_t n, casing_suffix_context_t a_context)
27 casing_suffix_context_t context;
28 /* Evaluate all three conditions in a single pass through the string S.
29 The three variables are -1 as long as the value of the condition has
30 not been determined. */
31 ucs4_t first_char_except_ignorable = (ucs4_t)(-1);
32 int scc_MORE_ABOVE = -1;
33 int scc_BEFORE_DOT = -1;
34 const UNIT *s_end = s + n;
36 while (s < s_end)
38 ucs4_t uc;
39 int count = U_MBTOUC_UNSAFE (&uc, s, s_end - s);
41 if (first_char_except_ignorable == (ucs4_t)(-1))
43 if (!uc_is_case_ignorable (uc))
44 first_char_except_ignorable = uc;
47 if (scc_MORE_ABOVE < 0)
49 int ccc = uc_combining_class (uc);
50 if (ccc == UC_CCC_A)
51 scc_MORE_ABOVE = SCC_MORE_ABOVE_MASK;
52 else if (ccc == UC_CCC_NR)
53 scc_MORE_ABOVE = 0;
56 if (scc_BEFORE_DOT < 0)
58 if (uc == 0x0307) /* COMBINING DOT ABOVE */
59 scc_BEFORE_DOT = SCC_BEFORE_DOT_MASK;
60 else
62 int ccc = uc_combining_class (uc);
63 if (ccc == UC_CCC_A || ccc == UC_CCC_NR)
64 scc_BEFORE_DOT = 0;
68 if (first_char_except_ignorable != (ucs4_t)(-1)
69 && (scc_MORE_ABOVE | scc_BEFORE_DOT) >= 0)
70 /* All conditions have been determined. */
71 break;
73 s += count;
76 /* For those conditions that have not been determined so far, use the
77 value from the argument context. */
78 context.first_char_except_ignorable =
79 (first_char_except_ignorable != (ucs4_t)(-1)
80 ? first_char_except_ignorable
81 : a_context.first_char_except_ignorable);
82 context.bits =
83 (scc_MORE_ABOVE >= 0
84 ? scc_MORE_ABOVE
85 : a_context.bits & SCC_MORE_ABOVE_MASK)
86 | (scc_BEFORE_DOT >= 0
87 ? scc_BEFORE_DOT
88 : a_context.bits & SCC_BEFORE_DOT_MASK);
89 return context;