19f806850SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
244594c2fSOlaf Weber /*
344594c2fSOlaf Weber * Copyright (c) 2014 SGI.
444594c2fSOlaf Weber * All rights reserved.
544594c2fSOlaf Weber */
644594c2fSOlaf Weber
744594c2fSOlaf Weber #include "utf8n.h"
844594c2fSOlaf Weber
utf8version_is_supported(const struct unicode_map * um,unsigned int version)92b3d0478SChristoph Hellwig int utf8version_is_supported(const struct unicode_map *um, unsigned int version)
1044594c2fSOlaf Weber {
112b3d0478SChristoph Hellwig int i = um->tables->utf8agetab_size - 1;
1244594c2fSOlaf Weber
132b3d0478SChristoph Hellwig while (i >= 0 && um->tables->utf8agetab[i] != 0) {
142b3d0478SChristoph Hellwig if (version == um->tables->utf8agetab[i])
1544594c2fSOlaf Weber return 1;
1644594c2fSOlaf Weber i--;
1744594c2fSOlaf Weber }
1844594c2fSOlaf Weber return 0;
1944594c2fSOlaf Weber }
2044594c2fSOlaf Weber
2144594c2fSOlaf Weber /*
2244594c2fSOlaf Weber * UTF-8 valid ranges.
2344594c2fSOlaf Weber *
2444594c2fSOlaf Weber * The UTF-8 encoding spreads the bits of a 32bit word over several
2544594c2fSOlaf Weber * bytes. This table gives the ranges that can be held and how they'd
2644594c2fSOlaf Weber * be represented.
2744594c2fSOlaf Weber *
2844594c2fSOlaf Weber * 0x00000000 0x0000007F: 0xxxxxxx
2944594c2fSOlaf Weber * 0x00000000 0x000007FF: 110xxxxx 10xxxxxx
3044594c2fSOlaf Weber * 0x00000000 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
3144594c2fSOlaf Weber * 0x00000000 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
3244594c2fSOlaf Weber * 0x00000000 0x03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
3344594c2fSOlaf Weber * 0x00000000 0x7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
3444594c2fSOlaf Weber *
3544594c2fSOlaf Weber * There is an additional requirement on UTF-8, in that only the
3644594c2fSOlaf Weber * shortest representation of a 32bit value is to be used. A decoder
3744594c2fSOlaf Weber * must not decode sequences that do not satisfy this requirement.
3844594c2fSOlaf Weber * Thus the allowed ranges have a lower bound.
3944594c2fSOlaf Weber *
4044594c2fSOlaf Weber * 0x00000000 0x0000007F: 0xxxxxxx
4144594c2fSOlaf Weber * 0x00000080 0x000007FF: 110xxxxx 10xxxxxx
4244594c2fSOlaf Weber * 0x00000800 0x0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
4344594c2fSOlaf Weber * 0x00010000 0x001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
4444594c2fSOlaf Weber * 0x00200000 0x03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
4544594c2fSOlaf Weber * 0x04000000 0x7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
4644594c2fSOlaf Weber *
4744594c2fSOlaf Weber * Actual unicode characters are limited to the range 0x0 - 0x10FFFF,
4844594c2fSOlaf Weber * 17 planes of 65536 values. This limits the sequences actually seen
4944594c2fSOlaf Weber * even more, to just the following.
5044594c2fSOlaf Weber *
5144594c2fSOlaf Weber * 0 - 0x7F: 0 - 0x7F
5244594c2fSOlaf Weber * 0x80 - 0x7FF: 0xC2 0x80 - 0xDF 0xBF
5344594c2fSOlaf Weber * 0x800 - 0xFFFF: 0xE0 0xA0 0x80 - 0xEF 0xBF 0xBF
5444594c2fSOlaf Weber * 0x10000 - 0x10FFFF: 0xF0 0x90 0x80 0x80 - 0xF4 0x8F 0xBF 0xBF
5544594c2fSOlaf Weber *
5644594c2fSOlaf Weber * Within those ranges the surrogates 0xD800 - 0xDFFF are not allowed.
5744594c2fSOlaf Weber *
5844594c2fSOlaf Weber * Note that the longest sequence seen with valid usage is 4 bytes,
5944594c2fSOlaf Weber * the same a single UTF-32 character. This makes the UTF-8
6044594c2fSOlaf Weber * representation of Unicode strictly smaller than UTF-32.
6144594c2fSOlaf Weber *
6244594c2fSOlaf Weber * The shortest sequence requirement was introduced by:
6344594c2fSOlaf Weber * Corrigendum #1: UTF-8 Shortest Form
6444594c2fSOlaf Weber * It can be found here:
6544594c2fSOlaf Weber * http://www.unicode.org/versions/corrigendum1.html
6644594c2fSOlaf Weber *
6744594c2fSOlaf Weber */
6844594c2fSOlaf Weber
6944594c2fSOlaf Weber /*
7044594c2fSOlaf Weber * Return the number of bytes used by the current UTF-8 sequence.
7144594c2fSOlaf Weber * Assumes the input points to the first byte of a valid UTF-8
7244594c2fSOlaf Weber * sequence.
7344594c2fSOlaf Weber */
utf8clen(const char * s)7444594c2fSOlaf Weber static inline int utf8clen(const char *s)
7544594c2fSOlaf Weber {
7644594c2fSOlaf Weber unsigned char c = *s;
7744594c2fSOlaf Weber
7844594c2fSOlaf Weber return 1 + (c >= 0xC0) + (c >= 0xE0) + (c >= 0xF0);
7944594c2fSOlaf Weber }
8044594c2fSOlaf Weber
8144594c2fSOlaf Weber /*
82a8384c68SOlaf Weber * Decode a 3-byte UTF-8 sequence.
83a8384c68SOlaf Weber */
84a8384c68SOlaf Weber static unsigned int
utf8decode3(const char * str)85a8384c68SOlaf Weber utf8decode3(const char *str)
86a8384c68SOlaf Weber {
87a8384c68SOlaf Weber unsigned int uc;
88a8384c68SOlaf Weber
89a8384c68SOlaf Weber uc = *str++ & 0x0F;
90a8384c68SOlaf Weber uc <<= 6;
91a8384c68SOlaf Weber uc |= *str++ & 0x3F;
92a8384c68SOlaf Weber uc <<= 6;
93a8384c68SOlaf Weber uc |= *str++ & 0x3F;
94a8384c68SOlaf Weber
95a8384c68SOlaf Weber return uc;
96a8384c68SOlaf Weber }
97a8384c68SOlaf Weber
98a8384c68SOlaf Weber /*
99a8384c68SOlaf Weber * Encode a 3-byte UTF-8 sequence.
100a8384c68SOlaf Weber */
101a8384c68SOlaf Weber static int
utf8encode3(char * str,unsigned int val)102a8384c68SOlaf Weber utf8encode3(char *str, unsigned int val)
103a8384c68SOlaf Weber {
104a8384c68SOlaf Weber str[2] = (val & 0x3F) | 0x80;
105a8384c68SOlaf Weber val >>= 6;
106a8384c68SOlaf Weber str[1] = (val & 0x3F) | 0x80;
107a8384c68SOlaf Weber val >>= 6;
108a8384c68SOlaf Weber str[0] = val | 0xE0;
109a8384c68SOlaf Weber
110a8384c68SOlaf Weber return 3;
111a8384c68SOlaf Weber }
112a8384c68SOlaf Weber
113a8384c68SOlaf Weber /*
11444594c2fSOlaf Weber * utf8trie_t
11544594c2fSOlaf Weber *
11644594c2fSOlaf Weber * A compact binary tree, used to decode UTF-8 characters.
11744594c2fSOlaf Weber *
11844594c2fSOlaf Weber * Internal nodes are one byte for the node itself, and up to three
11944594c2fSOlaf Weber * bytes for an offset into the tree. The first byte contains the
12044594c2fSOlaf Weber * following information:
12144594c2fSOlaf Weber * NEXTBYTE - flag - advance to next byte if set
12244594c2fSOlaf Weber * BITNUM - 3 bit field - the bit number to tested
12344594c2fSOlaf Weber * OFFLEN - 2 bit field - number of bytes in the offset
12444594c2fSOlaf Weber * if offlen == 0 (non-branching node)
12544594c2fSOlaf Weber * RIGHTPATH - 1 bit field - set if the following node is for the
12644594c2fSOlaf Weber * right-hand path (tested bit is set)
12744594c2fSOlaf Weber * TRIENODE - 1 bit field - set if the following node is an internal
12844594c2fSOlaf Weber * node, otherwise it is a leaf node
12944594c2fSOlaf Weber * if offlen != 0 (branching node)
13044594c2fSOlaf Weber * LEFTNODE - 1 bit field - set if the left-hand node is internal
13144594c2fSOlaf Weber * RIGHTNODE - 1 bit field - set if the right-hand node is internal
13244594c2fSOlaf Weber *
13344594c2fSOlaf Weber * Due to the way utf8 works, there cannot be branching nodes with
13444594c2fSOlaf Weber * NEXTBYTE set, and moreover those nodes always have a righthand
13544594c2fSOlaf Weber * descendant.
13644594c2fSOlaf Weber */
13744594c2fSOlaf Weber typedef const unsigned char utf8trie_t;
13844594c2fSOlaf Weber #define BITNUM 0x07
13944594c2fSOlaf Weber #define NEXTBYTE 0x08
14044594c2fSOlaf Weber #define OFFLEN 0x30
14144594c2fSOlaf Weber #define OFFLEN_SHIFT 4
14244594c2fSOlaf Weber #define RIGHTPATH 0x40
14344594c2fSOlaf Weber #define TRIENODE 0x80
14444594c2fSOlaf Weber #define RIGHTNODE 0x40
14544594c2fSOlaf Weber #define LEFTNODE 0x80
14644594c2fSOlaf Weber
14744594c2fSOlaf Weber /*
14844594c2fSOlaf Weber * utf8leaf_t
14944594c2fSOlaf Weber *
15044594c2fSOlaf Weber * The leaves of the trie are embedded in the trie, and so the same
15144594c2fSOlaf Weber * underlying datatype: unsigned char.
15244594c2fSOlaf Weber *
15344594c2fSOlaf Weber * leaf[0]: The unicode version, stored as a generation number that is
1542b3d0478SChristoph Hellwig * an index into ->utf8agetab[]. With this we can filter code
15544594c2fSOlaf Weber * points based on the unicode version in which they were
15644594c2fSOlaf Weber * defined. The CCC of a non-defined code point is 0.
15744594c2fSOlaf Weber * leaf[1]: Canonical Combining Class. During normalization, we need
15844594c2fSOlaf Weber * to do a stable sort into ascending order of all characters
15944594c2fSOlaf Weber * with a non-zero CCC that occur between two characters with
16044594c2fSOlaf Weber * a CCC of 0, or at the begin or end of a string.
16144594c2fSOlaf Weber * The unicode standard guarantees that all CCC values are
16244594c2fSOlaf Weber * between 0 and 254 inclusive, which leaves 255 available as
16344594c2fSOlaf Weber * a special value.
16444594c2fSOlaf Weber * Code points with CCC 0 are known as stoppers.
16544594c2fSOlaf Weber * leaf[2]: Decomposition. If leaf[1] == 255, then leaf[2] is the
16644594c2fSOlaf Weber * start of a NUL-terminated string that is the decomposition
16744594c2fSOlaf Weber * of the character.
16844594c2fSOlaf Weber * The CCC of a decomposable character is the same as the CCC
16944594c2fSOlaf Weber * of the first character of its decomposition.
17044594c2fSOlaf Weber * Some characters decompose as the empty string: these are
17144594c2fSOlaf Weber * characters with the Default_Ignorable_Code_Point property.
17244594c2fSOlaf Weber * These do affect normalization, as they all have CCC 0.
17344594c2fSOlaf Weber *
174a8384c68SOlaf Weber * The decompositions in the trie have been fully expanded, with the
175a8384c68SOlaf Weber * exception of Hangul syllables, which are decomposed algorithmically.
17644594c2fSOlaf Weber *
17744594c2fSOlaf Weber * Casefolding, if applicable, is also done using decompositions.
17844594c2fSOlaf Weber *
17944594c2fSOlaf Weber * The trie is constructed in such a way that leaves exist for all
18044594c2fSOlaf Weber * UTF-8 sequences that match the criteria from the "UTF-8 valid
18144594c2fSOlaf Weber * ranges" comment above, and only for those sequences. Therefore a
18244594c2fSOlaf Weber * lookup in the trie can be used to validate the UTF-8 input.
18344594c2fSOlaf Weber */
18444594c2fSOlaf Weber typedef const unsigned char utf8leaf_t;
18544594c2fSOlaf Weber
18644594c2fSOlaf Weber #define LEAF_GEN(LEAF) ((LEAF)[0])
18744594c2fSOlaf Weber #define LEAF_CCC(LEAF) ((LEAF)[1])
18844594c2fSOlaf Weber #define LEAF_STR(LEAF) ((const char *)((LEAF) + 2))
18944594c2fSOlaf Weber
19044594c2fSOlaf Weber #define MINCCC (0)
19144594c2fSOlaf Weber #define MAXCCC (254)
19244594c2fSOlaf Weber #define STOPPER (0)
19344594c2fSOlaf Weber #define DECOMPOSE (255)
19444594c2fSOlaf Weber
195a8384c68SOlaf Weber /* Marker for hangul syllable decomposition. */
196a8384c68SOlaf Weber #define HANGUL ((char)(255))
197a8384c68SOlaf Weber /* Size of the synthesized leaf used for Hangul syllable decomposition. */
198a8384c68SOlaf Weber #define UTF8HANGULLEAF (12)
199a8384c68SOlaf Weber
200a8384c68SOlaf Weber /*
201a8384c68SOlaf Weber * Hangul decomposition (algorithm from Section 3.12 of Unicode 6.3.0)
202a8384c68SOlaf Weber *
203a8384c68SOlaf Weber * AC00;<Hangul Syllable, First>;Lo;0;L;;;;;N;;;;;
204a8384c68SOlaf Weber * D7A3;<Hangul Syllable, Last>;Lo;0;L;;;;;N;;;;;
205a8384c68SOlaf Weber *
206a8384c68SOlaf Weber * SBase = 0xAC00
207a8384c68SOlaf Weber * LBase = 0x1100
208a8384c68SOlaf Weber * VBase = 0x1161
209a8384c68SOlaf Weber * TBase = 0x11A7
210a8384c68SOlaf Weber * LCount = 19
211a8384c68SOlaf Weber * VCount = 21
212a8384c68SOlaf Weber * TCount = 28
213a8384c68SOlaf Weber * NCount = 588 (VCount * TCount)
214a8384c68SOlaf Weber * SCount = 11172 (LCount * NCount)
215a8384c68SOlaf Weber *
216a8384c68SOlaf Weber * Decomposition:
217a8384c68SOlaf Weber * SIndex = s - SBase
218a8384c68SOlaf Weber *
219a8384c68SOlaf Weber * LV (Canonical/Full)
220a8384c68SOlaf Weber * LIndex = SIndex / NCount
221a8384c68SOlaf Weber * VIndex = (Sindex % NCount) / TCount
222a8384c68SOlaf Weber * LPart = LBase + LIndex
223a8384c68SOlaf Weber * VPart = VBase + VIndex
224a8384c68SOlaf Weber *
225a8384c68SOlaf Weber * LVT (Canonical)
226a8384c68SOlaf Weber * LVIndex = (SIndex / TCount) * TCount
227a8384c68SOlaf Weber * TIndex = (Sindex % TCount)
228a8384c68SOlaf Weber * LVPart = SBase + LVIndex
229a8384c68SOlaf Weber * TPart = TBase + TIndex
230a8384c68SOlaf Weber *
231a8384c68SOlaf Weber * LVT (Full)
232a8384c68SOlaf Weber * LIndex = SIndex / NCount
233a8384c68SOlaf Weber * VIndex = (Sindex % NCount) / TCount
234a8384c68SOlaf Weber * TIndex = (Sindex % TCount)
235a8384c68SOlaf Weber * LPart = LBase + LIndex
236a8384c68SOlaf Weber * VPart = VBase + VIndex
237a8384c68SOlaf Weber * if (TIndex == 0) {
238a8384c68SOlaf Weber * d = <LPart, VPart>
239a8384c68SOlaf Weber * } else {
240a8384c68SOlaf Weber * TPart = TBase + TIndex
241a8384c68SOlaf Weber * d = <LPart, TPart, VPart>
242a8384c68SOlaf Weber * }
243a8384c68SOlaf Weber */
244a8384c68SOlaf Weber
245a8384c68SOlaf Weber /* Constants */
246a8384c68SOlaf Weber #define SB (0xAC00)
247a8384c68SOlaf Weber #define LB (0x1100)
248a8384c68SOlaf Weber #define VB (0x1161)
249a8384c68SOlaf Weber #define TB (0x11A7)
250a8384c68SOlaf Weber #define LC (19)
251a8384c68SOlaf Weber #define VC (21)
252a8384c68SOlaf Weber #define TC (28)
253a8384c68SOlaf Weber #define NC (VC * TC)
254a8384c68SOlaf Weber #define SC (LC * NC)
255a8384c68SOlaf Weber
256a8384c68SOlaf Weber /* Algorithmic decomposition of hangul syllable. */
257a8384c68SOlaf Weber static utf8leaf_t *
utf8hangul(const char * str,unsigned char * hangul)258a8384c68SOlaf Weber utf8hangul(const char *str, unsigned char *hangul)
259a8384c68SOlaf Weber {
260a8384c68SOlaf Weber unsigned int si;
261a8384c68SOlaf Weber unsigned int li;
262a8384c68SOlaf Weber unsigned int vi;
263a8384c68SOlaf Weber unsigned int ti;
264a8384c68SOlaf Weber unsigned char *h;
265a8384c68SOlaf Weber
266a8384c68SOlaf Weber /* Calculate the SI, LI, VI, and TI values. */
267a8384c68SOlaf Weber si = utf8decode3(str) - SB;
268a8384c68SOlaf Weber li = si / NC;
269a8384c68SOlaf Weber vi = (si % NC) / TC;
270a8384c68SOlaf Weber ti = si % TC;
271a8384c68SOlaf Weber
272a8384c68SOlaf Weber /* Fill in base of leaf. */
273a8384c68SOlaf Weber h = hangul;
274a8384c68SOlaf Weber LEAF_GEN(h) = 2;
275a8384c68SOlaf Weber LEAF_CCC(h) = DECOMPOSE;
276a8384c68SOlaf Weber h += 2;
277a8384c68SOlaf Weber
278a8384c68SOlaf Weber /* Add LPart, a 3-byte UTF-8 sequence. */
279a8384c68SOlaf Weber h += utf8encode3((char *)h, li + LB);
280a8384c68SOlaf Weber
281a8384c68SOlaf Weber /* Add VPart, a 3-byte UTF-8 sequence. */
282a8384c68SOlaf Weber h += utf8encode3((char *)h, vi + VB);
283a8384c68SOlaf Weber
284a8384c68SOlaf Weber /* Add TPart if required, also a 3-byte UTF-8 sequence. */
285a8384c68SOlaf Weber if (ti)
286a8384c68SOlaf Weber h += utf8encode3((char *)h, ti + TB);
287a8384c68SOlaf Weber
288a8384c68SOlaf Weber /* Terminate string. */
289a8384c68SOlaf Weber h[0] = '\0';
290a8384c68SOlaf Weber
291a8384c68SOlaf Weber return hangul;
292a8384c68SOlaf Weber }
293a8384c68SOlaf Weber
29444594c2fSOlaf Weber /*
29544594c2fSOlaf Weber * Use trie to scan s, touching at most len bytes.
29644594c2fSOlaf Weber * Returns the leaf if one exists, NULL otherwise.
29744594c2fSOlaf Weber *
29844594c2fSOlaf Weber * A non-NULL return guarantees that the UTF-8 sequence starting at s
29944594c2fSOlaf Weber * is well-formed and corresponds to a known unicode code point. The
30044594c2fSOlaf Weber * shorthand for this will be "is valid UTF-8 unicode".
30144594c2fSOlaf Weber */
utf8nlookup(const struct unicode_map * um,enum utf8_normalization n,unsigned char * hangul,const char * s,size_t len)3026ca99ce7SChristoph Hellwig static utf8leaf_t *utf8nlookup(const struct unicode_map *um,
3036ca99ce7SChristoph Hellwig enum utf8_normalization n, unsigned char *hangul, const char *s,
3046ca99ce7SChristoph Hellwig size_t len)
30544594c2fSOlaf Weber {
3062b3d0478SChristoph Hellwig utf8trie_t *trie = um->tables->utf8data + um->ntab[n]->offset;
30744594c2fSOlaf Weber int offlen;
30844594c2fSOlaf Weber int offset;
30944594c2fSOlaf Weber int mask;
31044594c2fSOlaf Weber int node;
31144594c2fSOlaf Weber
31244594c2fSOlaf Weber if (len == 0)
31344594c2fSOlaf Weber return NULL;
31444594c2fSOlaf Weber
31544594c2fSOlaf Weber node = 1;
31644594c2fSOlaf Weber while (node) {
31744594c2fSOlaf Weber offlen = (*trie & OFFLEN) >> OFFLEN_SHIFT;
31844594c2fSOlaf Weber if (*trie & NEXTBYTE) {
31944594c2fSOlaf Weber if (--len == 0)
32044594c2fSOlaf Weber return NULL;
32144594c2fSOlaf Weber s++;
32244594c2fSOlaf Weber }
32344594c2fSOlaf Weber mask = 1 << (*trie & BITNUM);
32444594c2fSOlaf Weber if (*s & mask) {
32544594c2fSOlaf Weber /* Right leg */
32644594c2fSOlaf Weber if (offlen) {
32744594c2fSOlaf Weber /* Right node at offset of trie */
32844594c2fSOlaf Weber node = (*trie & RIGHTNODE);
32944594c2fSOlaf Weber offset = trie[offlen];
33044594c2fSOlaf Weber while (--offlen) {
33144594c2fSOlaf Weber offset <<= 8;
33244594c2fSOlaf Weber offset |= trie[offlen];
33344594c2fSOlaf Weber }
33444594c2fSOlaf Weber trie += offset;
33544594c2fSOlaf Weber } else if (*trie & RIGHTPATH) {
33644594c2fSOlaf Weber /* Right node after this node */
33744594c2fSOlaf Weber node = (*trie & TRIENODE);
33844594c2fSOlaf Weber trie++;
33944594c2fSOlaf Weber } else {
34044594c2fSOlaf Weber /* No right node. */
341a8384c68SOlaf Weber return NULL;
34244594c2fSOlaf Weber }
34344594c2fSOlaf Weber } else {
34444594c2fSOlaf Weber /* Left leg */
34544594c2fSOlaf Weber if (offlen) {
34644594c2fSOlaf Weber /* Left node after this node. */
34744594c2fSOlaf Weber node = (*trie & LEFTNODE);
34844594c2fSOlaf Weber trie += offlen + 1;
34944594c2fSOlaf Weber } else if (*trie & RIGHTPATH) {
35044594c2fSOlaf Weber /* No left node. */
351a8384c68SOlaf Weber return NULL;
35244594c2fSOlaf Weber } else {
35344594c2fSOlaf Weber /* Left node after this node */
35444594c2fSOlaf Weber node = (*trie & TRIENODE);
35544594c2fSOlaf Weber trie++;
35644594c2fSOlaf Weber }
35744594c2fSOlaf Weber }
35844594c2fSOlaf Weber }
359a8384c68SOlaf Weber /*
360a8384c68SOlaf Weber * Hangul decomposition is done algorithmically. These are the
361a8384c68SOlaf Weber * codepoints >= 0xAC00 and <= 0xD7A3. Their UTF-8 encoding is
362a8384c68SOlaf Weber * always 3 bytes long, so s has been advanced twice, and the
363a8384c68SOlaf Weber * start of the sequence is at s-2.
364a8384c68SOlaf Weber */
365a8384c68SOlaf Weber if (LEAF_CCC(trie) == DECOMPOSE && LEAF_STR(trie)[0] == HANGUL)
366a8384c68SOlaf Weber trie = utf8hangul(s - 2, hangul);
36744594c2fSOlaf Weber return trie;
36844594c2fSOlaf Weber }
36944594c2fSOlaf Weber
37044594c2fSOlaf Weber /*
37144594c2fSOlaf Weber * Use trie to scan s.
37244594c2fSOlaf Weber * Returns the leaf if one exists, NULL otherwise.
37344594c2fSOlaf Weber *
37444594c2fSOlaf Weber * Forwards to utf8nlookup().
37544594c2fSOlaf Weber */
utf8lookup(const struct unicode_map * um,enum utf8_normalization n,unsigned char * hangul,const char * s)3766ca99ce7SChristoph Hellwig static utf8leaf_t *utf8lookup(const struct unicode_map *um,
3776ca99ce7SChristoph Hellwig enum utf8_normalization n, unsigned char *hangul, const char *s)
37844594c2fSOlaf Weber {
3796ca99ce7SChristoph Hellwig return utf8nlookup(um, n, hangul, s, (size_t)-1);
38044594c2fSOlaf Weber }
38144594c2fSOlaf Weber
38244594c2fSOlaf Weber /*
38344594c2fSOlaf Weber * Length of the normalization of s, touch at most len bytes.
38444594c2fSOlaf Weber * Return -1 if s is not valid UTF-8 unicode.
38544594c2fSOlaf Weber */
utf8nlen(const struct unicode_map * um,enum utf8_normalization n,const char * s,size_t len)3866ca99ce7SChristoph Hellwig ssize_t utf8nlen(const struct unicode_map *um, enum utf8_normalization n,
3876ca99ce7SChristoph Hellwig const char *s, size_t len)
38844594c2fSOlaf Weber {
38944594c2fSOlaf Weber utf8leaf_t *leaf;
39044594c2fSOlaf Weber size_t ret = 0;
391a8384c68SOlaf Weber unsigned char hangul[UTF8HANGULLEAF];
39244594c2fSOlaf Weber
39344594c2fSOlaf Weber while (len && *s) {
3946ca99ce7SChristoph Hellwig leaf = utf8nlookup(um, n, hangul, s, len);
39544594c2fSOlaf Weber if (!leaf)
39644594c2fSOlaf Weber return -1;
3972b3d0478SChristoph Hellwig if (um->tables->utf8agetab[LEAF_GEN(leaf)] >
3982b3d0478SChristoph Hellwig um->ntab[n]->maxage)
39944594c2fSOlaf Weber ret += utf8clen(s);
40044594c2fSOlaf Weber else if (LEAF_CCC(leaf) == DECOMPOSE)
40144594c2fSOlaf Weber ret += strlen(LEAF_STR(leaf));
40244594c2fSOlaf Weber else
40344594c2fSOlaf Weber ret += utf8clen(s);
40444594c2fSOlaf Weber len -= utf8clen(s);
40544594c2fSOlaf Weber s += utf8clen(s);
40644594c2fSOlaf Weber }
40744594c2fSOlaf Weber return ret;
40844594c2fSOlaf Weber }
40944594c2fSOlaf Weber
41044594c2fSOlaf Weber /*
41144594c2fSOlaf Weber * Set up an utf8cursor for use by utf8byte().
41244594c2fSOlaf Weber *
41344594c2fSOlaf Weber * u8c : pointer to cursor.
41444594c2fSOlaf Weber * data : const struct utf8data to use for normalization.
41544594c2fSOlaf Weber * s : string.
41644594c2fSOlaf Weber * len : length of s.
41744594c2fSOlaf Weber *
41844594c2fSOlaf Weber * Returns -1 on error, 0 on success.
41944594c2fSOlaf Weber */
utf8ncursor(struct utf8cursor * u8c,const struct unicode_map * um,enum utf8_normalization n,const char * s,size_t len)4206ca99ce7SChristoph Hellwig int utf8ncursor(struct utf8cursor *u8c, const struct unicode_map *um,
4216ca99ce7SChristoph Hellwig enum utf8_normalization n, const char *s, size_t len)
42244594c2fSOlaf Weber {
42344594c2fSOlaf Weber if (!s)
42444594c2fSOlaf Weber return -1;
4256ca99ce7SChristoph Hellwig u8c->um = um;
4266ca99ce7SChristoph Hellwig u8c->n = n;
42744594c2fSOlaf Weber u8c->s = s;
42844594c2fSOlaf Weber u8c->p = NULL;
42944594c2fSOlaf Weber u8c->ss = NULL;
43044594c2fSOlaf Weber u8c->sp = NULL;
43144594c2fSOlaf Weber u8c->len = len;
43244594c2fSOlaf Weber u8c->slen = 0;
43344594c2fSOlaf Weber u8c->ccc = STOPPER;
43444594c2fSOlaf Weber u8c->nccc = STOPPER;
43544594c2fSOlaf Weber /* Check we didn't clobber the maximum length. */
43644594c2fSOlaf Weber if (u8c->len != len)
43744594c2fSOlaf Weber return -1;
43844594c2fSOlaf Weber /* The first byte of s may not be an utf8 continuation. */
43944594c2fSOlaf Weber if (len > 0 && (*s & 0xC0) == 0x80)
44044594c2fSOlaf Weber return -1;
44144594c2fSOlaf Weber return 0;
44244594c2fSOlaf Weber }
44344594c2fSOlaf Weber
44444594c2fSOlaf Weber /*
44544594c2fSOlaf Weber * Get one byte from the normalized form of the string described by u8c.
44644594c2fSOlaf Weber *
44744594c2fSOlaf Weber * Returns the byte cast to an unsigned char on succes, and -1 on failure.
44844594c2fSOlaf Weber *
44944594c2fSOlaf Weber * The cursor keeps track of the location in the string in u8c->s.
45044594c2fSOlaf Weber * When a character is decomposed, the current location is stored in
45144594c2fSOlaf Weber * u8c->p, and u8c->s is set to the start of the decomposition. Note
45244594c2fSOlaf Weber * that bytes from a decomposition do not count against u8c->len.
45344594c2fSOlaf Weber *
45444594c2fSOlaf Weber * Characters are emitted if they match the current CCC in u8c->ccc.
45544594c2fSOlaf Weber * Hitting end-of-string while u8c->ccc == STOPPER means we're done,
45644594c2fSOlaf Weber * and the function returns 0 in that case.
45744594c2fSOlaf Weber *
45844594c2fSOlaf Weber * Sorting by CCC is done by repeatedly scanning the string. The
45944594c2fSOlaf Weber * values of u8c->s and u8c->p are stored in u8c->ss and u8c->sp at
46044594c2fSOlaf Weber * the start of the scan. The first pass finds the lowest CCC to be
46144594c2fSOlaf Weber * emitted and stores it in u8c->nccc, the second pass emits the
46244594c2fSOlaf Weber * characters with this CCC and finds the next lowest CCC. This limits
46344594c2fSOlaf Weber * the number of passes to 1 + the number of different CCCs in the
46444594c2fSOlaf Weber * sequence being scanned.
46544594c2fSOlaf Weber *
46644594c2fSOlaf Weber * Therefore:
46744594c2fSOlaf Weber * u8c->p != NULL -> a decomposition is being scanned.
46844594c2fSOlaf Weber * u8c->ss != NULL -> this is a repeating scan.
46944594c2fSOlaf Weber * u8c->ccc == -1 -> this is the first scan of a repeating scan.
47044594c2fSOlaf Weber */
utf8byte(struct utf8cursor * u8c)47144594c2fSOlaf Weber int utf8byte(struct utf8cursor *u8c)
47244594c2fSOlaf Weber {
47344594c2fSOlaf Weber utf8leaf_t *leaf;
47444594c2fSOlaf Weber int ccc;
47544594c2fSOlaf Weber
47644594c2fSOlaf Weber for (;;) {
47744594c2fSOlaf Weber /* Check for the end of a decomposed character. */
47844594c2fSOlaf Weber if (u8c->p && *u8c->s == '\0') {
47944594c2fSOlaf Weber u8c->s = u8c->p;
48044594c2fSOlaf Weber u8c->p = NULL;
48144594c2fSOlaf Weber }
48244594c2fSOlaf Weber
48344594c2fSOlaf Weber /* Check for end-of-string. */
48444594c2fSOlaf Weber if (!u8c->p && (u8c->len == 0 || *u8c->s == '\0')) {
48544594c2fSOlaf Weber /* There is no next byte. */
48644594c2fSOlaf Weber if (u8c->ccc == STOPPER)
48744594c2fSOlaf Weber return 0;
48844594c2fSOlaf Weber /* End-of-string during a scan counts as a stopper. */
48944594c2fSOlaf Weber ccc = STOPPER;
49044594c2fSOlaf Weber goto ccc_mismatch;
49144594c2fSOlaf Weber } else if ((*u8c->s & 0xC0) == 0x80) {
49244594c2fSOlaf Weber /* This is a continuation of the current character. */
49344594c2fSOlaf Weber if (!u8c->p)
49444594c2fSOlaf Weber u8c->len--;
49544594c2fSOlaf Weber return (unsigned char)*u8c->s++;
49644594c2fSOlaf Weber }
49744594c2fSOlaf Weber
49844594c2fSOlaf Weber /* Look up the data for the current character. */
499a8384c68SOlaf Weber if (u8c->p) {
5006ca99ce7SChristoph Hellwig leaf = utf8lookup(u8c->um, u8c->n, u8c->hangul, u8c->s);
501a8384c68SOlaf Weber } else {
5026ca99ce7SChristoph Hellwig leaf = utf8nlookup(u8c->um, u8c->n, u8c->hangul,
503a8384c68SOlaf Weber u8c->s, u8c->len);
504a8384c68SOlaf Weber }
50544594c2fSOlaf Weber
50644594c2fSOlaf Weber /* No leaf found implies that the input is a binary blob. */
50744594c2fSOlaf Weber if (!leaf)
50844594c2fSOlaf Weber return -1;
50944594c2fSOlaf Weber
51044594c2fSOlaf Weber ccc = LEAF_CCC(leaf);
51144594c2fSOlaf Weber /* Characters that are too new have CCC 0. */
5122b3d0478SChristoph Hellwig if (u8c->um->tables->utf8agetab[LEAF_GEN(leaf)] >
5136ca99ce7SChristoph Hellwig u8c->um->ntab[u8c->n]->maxage) {
51444594c2fSOlaf Weber ccc = STOPPER;
51544594c2fSOlaf Weber } else if (ccc == DECOMPOSE) {
51644594c2fSOlaf Weber u8c->len -= utf8clen(u8c->s);
51744594c2fSOlaf Weber u8c->p = u8c->s + utf8clen(u8c->s);
51844594c2fSOlaf Weber u8c->s = LEAF_STR(leaf);
51944594c2fSOlaf Weber /* Empty decomposition implies CCC 0. */
52044594c2fSOlaf Weber if (*u8c->s == '\0') {
52144594c2fSOlaf Weber if (u8c->ccc == STOPPER)
52244594c2fSOlaf Weber continue;
52344594c2fSOlaf Weber ccc = STOPPER;
52444594c2fSOlaf Weber goto ccc_mismatch;
52544594c2fSOlaf Weber }
526a8384c68SOlaf Weber
5276ca99ce7SChristoph Hellwig leaf = utf8lookup(u8c->um, u8c->n, u8c->hangul, u8c->s);
52815f0d8d0STheodore Ts'o if (!leaf)
52915f0d8d0STheodore Ts'o return -1;
530a8384c68SOlaf Weber ccc = LEAF_CCC(leaf);
53144594c2fSOlaf Weber }
53244594c2fSOlaf Weber
53344594c2fSOlaf Weber /*
53444594c2fSOlaf Weber * If this is not a stopper, then see if it updates
53544594c2fSOlaf Weber * the next canonical class to be emitted.
53644594c2fSOlaf Weber */
53744594c2fSOlaf Weber if (ccc != STOPPER && u8c->ccc < ccc && ccc < u8c->nccc)
53844594c2fSOlaf Weber u8c->nccc = ccc;
53944594c2fSOlaf Weber
54044594c2fSOlaf Weber /*
54144594c2fSOlaf Weber * Return the current byte if this is the current
54244594c2fSOlaf Weber * combining class.
54344594c2fSOlaf Weber */
54444594c2fSOlaf Weber if (ccc == u8c->ccc) {
54544594c2fSOlaf Weber if (!u8c->p)
54644594c2fSOlaf Weber u8c->len--;
54744594c2fSOlaf Weber return (unsigned char)*u8c->s++;
54844594c2fSOlaf Weber }
54944594c2fSOlaf Weber
55044594c2fSOlaf Weber /* Current combining class mismatch. */
55144594c2fSOlaf Weber ccc_mismatch:
55244594c2fSOlaf Weber if (u8c->nccc == STOPPER) {
55344594c2fSOlaf Weber /*
55444594c2fSOlaf Weber * Scan forward for the first canonical class
55544594c2fSOlaf Weber * to be emitted. Save the position from
55644594c2fSOlaf Weber * which to restart.
55744594c2fSOlaf Weber */
55844594c2fSOlaf Weber u8c->ccc = MINCCC - 1;
55944594c2fSOlaf Weber u8c->nccc = ccc;
56044594c2fSOlaf Weber u8c->sp = u8c->p;
56144594c2fSOlaf Weber u8c->ss = u8c->s;
56244594c2fSOlaf Weber u8c->slen = u8c->len;
56344594c2fSOlaf Weber if (!u8c->p)
56444594c2fSOlaf Weber u8c->len -= utf8clen(u8c->s);
56544594c2fSOlaf Weber u8c->s += utf8clen(u8c->s);
56644594c2fSOlaf Weber } else if (ccc != STOPPER) {
56744594c2fSOlaf Weber /* Not a stopper, and not the ccc we're emitting. */
56844594c2fSOlaf Weber if (!u8c->p)
56944594c2fSOlaf Weber u8c->len -= utf8clen(u8c->s);
57044594c2fSOlaf Weber u8c->s += utf8clen(u8c->s);
57144594c2fSOlaf Weber } else if (u8c->nccc != MAXCCC + 1) {
57244594c2fSOlaf Weber /* At a stopper, restart for next ccc. */
57344594c2fSOlaf Weber u8c->ccc = u8c->nccc;
57444594c2fSOlaf Weber u8c->nccc = MAXCCC + 1;
57544594c2fSOlaf Weber u8c->s = u8c->ss;
57644594c2fSOlaf Weber u8c->p = u8c->sp;
57744594c2fSOlaf Weber u8c->len = u8c->slen;
57844594c2fSOlaf Weber } else {
57944594c2fSOlaf Weber /* All done, proceed from here. */
58044594c2fSOlaf Weber u8c->ccc = STOPPER;
58144594c2fSOlaf Weber u8c->nccc = STOPPER;
58244594c2fSOlaf Weber u8c->sp = NULL;
58344594c2fSOlaf Weber u8c->ss = NULL;
58444594c2fSOlaf Weber u8c->slen = 0;
58544594c2fSOlaf Weber }
58644594c2fSOlaf Weber }
58744594c2fSOlaf Weber }
588*e2a58d2dSChristoph Hellwig
589*e2a58d2dSChristoph Hellwig #ifdef CONFIG_UNICODE_NORMALIZATION_SELFTEST_MODULE
590*e2a58d2dSChristoph Hellwig EXPORT_SYMBOL_GPL(utf8version_is_supported);
591*e2a58d2dSChristoph Hellwig EXPORT_SYMBOL_GPL(utf8nlen);
592*e2a58d2dSChristoph Hellwig EXPORT_SYMBOL_GPL(utf8ncursor);
593*e2a58d2dSChristoph Hellwig EXPORT_SYMBOL_GPL(utf8byte);
594*e2a58d2dSChristoph Hellwig #endif
595