]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - fs/ntfs3/upcase.c
fs/ntfs3: Restyle comments to better align with kernel-doc
[mirror_ubuntu-kernels.git] / fs / ntfs3 / upcase.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 *
4 * Copyright (C) 2019-2021 Paragon Software GmbH, All rights reserved.
5 *
6 */
7
8 #include <linux/blkdev.h>
9 #include <linux/buffer_head.h>
10 #include <linux/module.h>
11 #include <linux/nls.h>
12
13 #include "debug.h"
14 #include "ntfs.h"
15 #include "ntfs_fs.h"
16
17 static inline u16 upcase_unicode_char(const u16 *upcase, u16 chr)
18 {
19 if (chr < 'a')
20 return chr;
21
22 if (chr <= 'z')
23 return chr - ('a' - 'A');
24
25 return upcase[chr];
26 }
27
28 /*
29 * ntfs_cmp_names
30 *
31 * Thanks Kari Argillander <kari.argillander@gmail.com> for idea and implementation 'bothcase'
32 *
33 * Straight way to compare names:
34 * - Case insensitive
35 * - If name equals and 'bothcases' then
36 * - Case sensitive
37 * 'Straight way' code scans input names twice in worst case.
38 * Optimized code scans input names only once.
39 */
40 int ntfs_cmp_names(const __le16 *s1, size_t l1, const __le16 *s2, size_t l2,
41 const u16 *upcase, bool bothcase)
42 {
43 int diff1 = 0;
44 int diff2;
45 size_t len = min(l1, l2);
46
47 if (!bothcase && upcase)
48 goto case_insentive;
49
50 for (; len; s1++, s2++, len--) {
51 diff1 = le16_to_cpu(*s1) - le16_to_cpu(*s2);
52 if (diff1) {
53 if (bothcase && upcase)
54 goto case_insentive;
55
56 return diff1;
57 }
58 }
59 return l1 - l2;
60
61 case_insentive:
62 for (; len; s1++, s2++, len--) {
63 diff2 = upcase_unicode_char(upcase, le16_to_cpu(*s1)) -
64 upcase_unicode_char(upcase, le16_to_cpu(*s2));
65 if (diff2)
66 return diff2;
67 }
68
69 diff2 = l1 - l2;
70 return diff2 ? diff2 : diff1;
71 }
72
73 int ntfs_cmp_names_cpu(const struct cpu_str *uni1, const struct le_str *uni2,
74 const u16 *upcase, bool bothcase)
75 {
76 const u16 *s1 = uni1->name;
77 const __le16 *s2 = uni2->name;
78 size_t l1 = uni1->len;
79 size_t l2 = uni2->len;
80 size_t len = min(l1, l2);
81 int diff1 = 0;
82 int diff2;
83
84 if (!bothcase && upcase)
85 goto case_insentive;
86
87 for (; len; s1++, s2++, len--) {
88 diff1 = *s1 - le16_to_cpu(*s2);
89 if (diff1) {
90 if (bothcase && upcase)
91 goto case_insentive;
92
93 return diff1;
94 }
95 }
96 return l1 - l2;
97
98 case_insentive:
99 for (; len; s1++, s2++, len--) {
100 diff2 = upcase_unicode_char(upcase, *s1) -
101 upcase_unicode_char(upcase, le16_to_cpu(*s2));
102 if (diff2)
103 return diff2;
104 }
105
106 diff2 = l1 - l2;
107 return diff2 ? diff2 : diff1;
108 }