^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/hfsplus/unicode.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2001
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Brad Boyer (flar@allandria.com)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * (C) 2003 Ardis Technologies <roman@ardistech.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Handler routines for unicode strings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/nls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "hfsplus_fs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "hfsplus_raw.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) /* Fold the case of a unicode char, given the 16 bit value */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /* Returns folded char, or 0 if ignorable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) static inline u16 case_fold(u16 c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) u16 tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) tmp = hfsplus_case_fold_table[c >> 8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (tmp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) tmp = hfsplus_case_fold_table[tmp + (c & 0xff)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) tmp = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) return tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Compare unicode strings, return values like normal strcmp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int hfsplus_strcasecmp(const struct hfsplus_unistr *s1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) const struct hfsplus_unistr *s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) u16 len1, len2, c1, c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) const hfsplus_unichr *p1, *p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) len1 = be16_to_cpu(s1->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) len2 = be16_to_cpu(s2->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) p1 = s1->unicode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) p2 = s2->unicode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) c1 = c2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) while (len1 && !c1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) c1 = case_fold(be16_to_cpu(*p1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) p1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) len1--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) while (len2 && !c2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) c2 = case_fold(be16_to_cpu(*p2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) p2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) len2--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (c1 != c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return (c1 < c2) ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (!c1 && !c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* Compare names as a sequence of 16-bit unsigned integers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int hfsplus_strcmp(const struct hfsplus_unistr *s1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const struct hfsplus_unistr *s2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) u16 len1, len2, c1, c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) const hfsplus_unichr *p1, *p2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) len1 = be16_to_cpu(s1->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) len2 = be16_to_cpu(s2->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) p1 = s1->unicode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) p2 = s2->unicode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) for (len = min(len1, len2); len > 0; len--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) c1 = be16_to_cpu(*p1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) c2 = be16_to_cpu(*p2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) if (c1 != c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) return c1 < c2 ? -1 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) p1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) p2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return len1 < len2 ? -1 :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) len1 > len2 ? 1 : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #define Hangul_SBase 0xac00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) #define Hangul_LBase 0x1100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) #define Hangul_VBase 0x1161
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define Hangul_TBase 0x11a7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) #define Hangul_SCount 11172
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) #define Hangul_LCount 19
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) #define Hangul_VCount 21
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) #define Hangul_TCount 28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) #define Hangul_NCount (Hangul_VCount * Hangul_TCount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) static u16 *hfsplus_compose_lookup(u16 *p, u16 cc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int i, s, e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) s = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) e = p[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (!e || cc < p[s * 2] || cc > p[e * 2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) i = (s + e) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (cc > p[i * 2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) s = i + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) else if (cc < p[i * 2])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) e = i - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) return hfsplus_compose_table + p[i * 2 + 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) } while (s <= e);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) int hfsplus_uni2asc(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) const struct hfsplus_unistr *ustr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) char *astr, int *len_p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) const hfsplus_unichr *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) struct nls_table *nls = HFSPLUS_SB(sb)->nls;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) u8 *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) u16 cc, c0, c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) u16 *ce1, *ce2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) int i, len, ustrlen, res, compose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) op = astr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ip = ustr->unicode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) ustrlen = be16_to_cpu(ustr->length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) len = *len_p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) ce1 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) compose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) while (ustrlen > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) c0 = be16_to_cpu(*ip++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) ustrlen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* search for single decomposed char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (likely(compose))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) ce1 = hfsplus_compose_lookup(hfsplus_compose_table, c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (ce1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) cc = ce1[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) cc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) if (cc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) /* start of a possibly decomposed Hangul char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (cc != 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) if (!ustrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) goto same;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) c1 = be16_to_cpu(*ip) - Hangul_VBase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (c1 < Hangul_VCount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* compose the Hangul char */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) cc = (c0 - Hangul_LBase) * Hangul_VCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) cc = (cc + c1) * Hangul_TCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) cc += Hangul_SBase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ustrlen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) if (!ustrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) c1 = be16_to_cpu(*ip) - Hangul_TBase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (c1 > 0 && c1 < Hangul_TCount) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) cc += c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) ustrlen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* main loop for common case of not composed chars */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!ustrlen)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) goto same;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) c1 = be16_to_cpu(*ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) if (likely(compose))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) ce1 = hfsplus_compose_lookup(
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) hfsplus_compose_table, c1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (ce1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) switch (c0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) c0 = 0x2400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) case '/':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) c0 = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) res = nls->uni2char(c0, op, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) if (res < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (res == -ENAMETOOLONG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) *op = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) op += res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) len -= res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) c0 = c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) ip++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) ustrlen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) ce2 = hfsplus_compose_lookup(ce1, c0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (ce2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) i = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) while (i < ustrlen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) ce1 = hfsplus_compose_lookup(ce2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) be16_to_cpu(ip[i]));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) if (!ce1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) i++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) ce2 = ce1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) cc = ce2[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) if (cc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) ip += i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) ustrlen -= i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) same:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) switch (c0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) cc = 0x2400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) case '/':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) cc = ':';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) cc = c0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) res = nls->uni2char(cc, op, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (res < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) if (res == -ENAMETOOLONG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) *op = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) res = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) op += res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) len -= res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) res = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) *len_p = (char *)op - astr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) return res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * Convert one or more ASCII characters into a single unicode character.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * Returns the number of ASCII characters corresponding to the unicode char.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static inline int asc2unichar(struct super_block *sb, const char *astr, int len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) wchar_t *uc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int size = HFSPLUS_SB(sb)->nls->char2uni(astr, len, uc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (size <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) *uc = '?';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) size = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) switch (*uc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) case 0x2400:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) *uc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) case ':':
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) *uc = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /* Decomposes a non-Hangul unicode character. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) static u16 *hfsplus_decompose_nonhangul(wchar_t uc, int *size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) int off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) off = hfsplus_decompose_table[(uc >> 12) & 0xf];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) if (off == 0 || off == 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) if (!off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) if (!off)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) off = hfsplus_decompose_table[off + (uc & 0xf)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) *size = off & 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (*size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) return hfsplus_decompose_table + (off / 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) * Try to decompose a unicode character as Hangul. Return 0 if @uc is not
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * precomposed Hangul, otherwise return the length of the decomposition.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * This function was adapted from sample code from the Unicode Standard
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * Annex #15: Unicode Normalization Forms, version 3.2.0.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) * Copyright (C) 1991-2018 Unicode, Inc. All rights reserved. Distributed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * under the Terms of Use in http://www.unicode.org/copyright.html.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static int hfsplus_try_decompose_hangul(wchar_t uc, u16 *result)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) int l, v, t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) index = uc - Hangul_SBase;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) if (index < 0 || index >= Hangul_SCount)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) l = Hangul_LBase + index / Hangul_NCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) v = Hangul_VBase + (index % Hangul_NCount) / Hangul_TCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) t = Hangul_TBase + index % Hangul_TCount;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) result[0] = l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) result[1] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (t != Hangul_TBase) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) result[2] = t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) return 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) /* Decomposes a single unicode character. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) static u16 *decompose_unichar(wchar_t uc, int *size, u16 *hangul_buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) u16 *result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) /* Hangul is handled separately */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) result = hangul_buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *size = hfsplus_try_decompose_hangul(uc, result);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) if (*size == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) result = hfsplus_decompose_nonhangul(uc, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return result;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) int hfsplus_asc2uni(struct super_block *sb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct hfsplus_unistr *ustr, int max_unistr_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) const char *astr, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) int size, dsize, decompose;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) u16 *dstr, outlen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) wchar_t c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) u16 dhangul[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) while (outlen < max_unistr_len && len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) size = asc2unichar(sb, astr, len, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (decompose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) dstr = decompose_unichar(c, &dsize, dhangul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) dstr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) if (dstr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) if (outlen + dsize > max_unistr_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) ustr->unicode[outlen++] = cpu_to_be16(*dstr++);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) } while (--dsize > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) ustr->unicode[outlen++] = cpu_to_be16(c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) astr += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) len -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) ustr->length = cpu_to_be16(outlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) if (len > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) return -ENAMETOOLONG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * Hash a string to an integer as appropriate for the HFS+ filesystem.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * Composed unicode characters are decomposed and case-folding is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * if the appropriate bits are (un)set on the superblock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) int hfsplus_hash_dentry(const struct dentry *dentry, struct qstr *str)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) struct super_block *sb = dentry->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) const char *astr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) const u16 *dstr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int casefold, decompose, size, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) unsigned long hash;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) wchar_t c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) u16 c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) u16 dhangul[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) hash = init_name_hash(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) astr = str->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) len = str->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) while (len > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) int dsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) size = asc2unichar(sb, astr, len, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) astr += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) len -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (decompose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) dstr = decompose_unichar(c, &dsize, dhangul);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) dstr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) if (dstr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) c2 = *dstr++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) if (casefold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) c2 = case_fold(c2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) if (!casefold || c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) hash = partial_name_hash(c2, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) } while (--dsize > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) c2 = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (casefold)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) c2 = case_fold(c2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!casefold || c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) hash = partial_name_hash(c2, hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) str->hash = end_name_hash(hash);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) * Compare strings with HFS+ filename ordering.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) * Composed unicode characters are decomposed and case-folding is performed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) * if the appropriate bits are (un)set on the superblock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int hfsplus_compare_dentry(const struct dentry *dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) unsigned int len, const char *str, const struct qstr *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) struct super_block *sb = dentry->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) int casefold, decompose, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) int dsize1, dsize2, len1, len2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) const u16 *dstr1, *dstr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) const char *astr1, *astr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) u16 c1, c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) wchar_t c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) u16 dhangul_1[3], dhangul_2[3];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) casefold = test_bit(HFSPLUS_SB_CASEFOLD, &HFSPLUS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) decompose = !test_bit(HFSPLUS_SB_NODECOMPOSE, &HFSPLUS_SB(sb)->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) astr1 = str;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) len1 = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) astr2 = name->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) len2 = name->len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) dsize1 = dsize2 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) dstr1 = dstr2 = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) while (len1 > 0 && len2 > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) if (!dsize1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) size = asc2unichar(sb, astr1, len1, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) astr1 += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) len1 -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) if (decompose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) dstr1 = decompose_unichar(c, &dsize1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) dhangul_1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (!decompose || !dstr1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) c1 = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) dstr1 = &c1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) dsize1 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (!dsize2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) size = asc2unichar(sb, astr2, len2, &c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) astr2 += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) len2 -= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) if (decompose)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) dstr2 = decompose_unichar(c, &dsize2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) dhangul_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) if (!decompose || !dstr2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) c2 = c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) dstr2 = &c2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) dsize2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) c1 = *dstr1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) c2 = *dstr2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) if (casefold) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) c1 = case_fold(c1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (!c1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dstr1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) dsize1--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) c2 = case_fold(c2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (!c2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) dstr2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) dsize2--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) if (c1 < c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) else if (c1 > c2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) dstr1++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dsize1--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) dstr2++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) dsize2--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (len1 < len2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (len1 > len2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) }