2 * linux/fs/hfsplus/unicode.c
5 * Brad Boyer (flar@allandria.com)
6 * (C) 2003 Ardis Technologies <roman@ardistech.com>
8 * Handler routines for unicode strings
11 #include <linux/types.h>
12 #include <linux/nls.h>
13 #include "hfsplus_fs.h"
14 #include "hfsplus_raw.h"
16 /* Fold the case of a unicode char, given the 16 bit value */
17 /* Returns folded char, or 0 if ignorable */
18 static inline u16
case_fold(u16 c
)
22 tmp
= hfsplus_case_fold_table
[c
>> 8];
24 tmp
= hfsplus_case_fold_table
[tmp
+ (c
& 0xff)];
30 /* Compare unicode strings, return values like normal strcmp */
31 int hfsplus_unistrcmp(const struct hfsplus_unistr
*s1
, const struct hfsplus_unistr
*s2
)
33 u16 len1
, len2
, c1
, c2
;
34 const hfsplus_unichr
*p1
, *p2
;
36 len1
= be16_to_cpu(s1
->length
);
37 len2
= be16_to_cpu(s2
->length
);
45 c1
= case_fold(be16_to_cpu(*p1
));
50 c2
= case_fold(be16_to_cpu(*p2
));
56 return (c1
< c2
) ? -1 : 1;
62 #define Hangul_SBase 0xac00
63 #define Hangul_LBase 0x1100
64 #define Hangul_VBase 0x1161
65 #define Hangul_TBase 0x11a7
66 #define Hangul_SCount 11172
67 #define Hangul_LCount 19
68 #define Hangul_VCount 21
69 #define Hangul_TCount 28
70 #define Hangul_NCount (Hangul_VCount * Hangul_TCount)
73 static u16
*hfsplus_compose_lookup(u16
*p
, u16 cc
)
79 if (!e
|| cc
< p
[s
* 2] || cc
> p
[e
* 2])
85 else if (cc
< p
[i
* 2])
88 return hfsplus_compose_table
+ p
[i
* 2 + 1];
93 int hfsplus_uni2asc(struct super_block
*sb
, const struct hfsplus_unistr
*ustr
, char *astr
, int *len_p
)
95 const hfsplus_unichr
*ip
;
96 struct nls_table
*nls
= HFSPLUS_SB(sb
).nls
;
100 int i
, len
, ustrlen
, res
, compose
;
104 ustrlen
= be16_to_cpu(ustr
->length
);
107 compose
= !(HFSPLUS_SB(sb
).flags
& HFSPLUS_SB_NODECOMPOSE
);
109 while (ustrlen
> 0) {
110 c0
= be16_to_cpu(*ip
++);
112 /* search for single decomposed char */
114 ce1
= hfsplus_compose_lookup(hfsplus_compose_table
, c0
);
115 if (ce1
&& (cc
= ce1
[0])) {
116 /* start of a possibly decomposed Hangul char */
121 c1
= be16_to_cpu(*ip
) - Hangul_VBase
;
122 if (c1
< Hangul_VCount
) {
123 /* compose the Hangul char */
124 cc
= (c0
- Hangul_LBase
) * Hangul_VCount
;
125 cc
= (cc
+ c1
) * Hangul_TCount
;
131 c1
= be16_to_cpu(*ip
) - Hangul_TBase
;
132 if (c1
> 0 && c1
< Hangul_TCount
) {
141 /* main loop for common case of not composed chars */
144 c1
= be16_to_cpu(*ip
);
146 ce1
= hfsplus_compose_lookup(hfsplus_compose_table
, c1
);
157 res
= nls
->uni2char(c0
, op
, len
);
159 if (res
== -ENAMETOOLONG
)
170 ce2
= hfsplus_compose_lookup(ce1
, c0
);
173 while (i
< ustrlen
) {
174 ce1
= hfsplus_compose_lookup(ce2
, be16_to_cpu(ip
[i
]));
198 res
= nls
->uni2char(cc
, op
, len
);
200 if (res
== -ENAMETOOLONG
)
210 *len_p
= (char *)op
- astr
;
214 int hfsplus_asc2uni(struct super_block
*sb
, struct hfsplus_unistr
*ustr
, const char *astr
, int len
)
216 struct nls_table
*nls
= HFSPLUS_SB(sb
).nls
;
217 int size
, off
, decompose
;
221 decompose
= !(HFSPLUS_SB(sb
).flags
& HFSPLUS_SB_NODECOMPOSE
);
223 while (outlen
< HFSPLUS_MAX_STRLEN
&& len
> 0) {
224 size
= nls
->char2uni(astr
, len
, &c
);
239 if (c
>= 0xc0 && decompose
) {
240 off
= hfsplus_decompose_table
[(c
>> 12) & 0xf];
246 off
= hfsplus_decompose_table
[off
+ ((c
>> 8) & 0xf)];
249 off
= hfsplus_decompose_table
[off
+ ((c
>> 4) & 0xf)];
252 off
= hfsplus_decompose_table
[off
+ (c
& 0xf)];
257 if (outlen
+ size
> HFSPLUS_MAX_STRLEN
)
260 ustr
->unicode
[outlen
++] = cpu_to_be16(hfsplus_decompose_table
[off
++]);
261 } while (--size
> 0);
265 ustr
->unicode
[outlen
++] = cpu_to_be16(c
);
267 ustr
->length
= cpu_to_be16(outlen
);
269 return -ENAMETOOLONG
;