Commit 2523c3fc2bc9e34c06a71517844d55353f1f904a
Committed by
David S. Miller
1 parent
3b76d08190
Exists in
master
and in
39 other branches
textsearch: ts_kmp: support case insensitive searching in Knuth-Morris-Pratt algorithm
Add support for case insensitive search to Knuth-Morris-Pratt algorithm. Signed-off-by: Joonwoo Park <joonwpark81@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
Showing 1 changed file with 21 additions and 8 deletions Side-by-side Diff
lib/ts_kmp.c
... | ... | @@ -33,6 +33,7 @@ |
33 | 33 | #include <linux/module.h> |
34 | 34 | #include <linux/types.h> |
35 | 35 | #include <linux/string.h> |
36 | +#include <linux/ctype.h> | |
36 | 37 | #include <linux/textsearch.h> |
37 | 38 | |
38 | 39 | struct ts_kmp |
... | ... | @@ -47,6 +48,7 @@ |
47 | 48 | struct ts_kmp *kmp = ts_config_priv(conf); |
48 | 49 | unsigned int i, q = 0, text_len, consumed = state->offset; |
49 | 50 | const u8 *text; |
51 | + const int icase = conf->flags & TS_IGNORECASE; | |
50 | 52 | |
51 | 53 | for (;;) { |
52 | 54 | text_len = conf->get_next_block(consumed, &text, conf, state); |
53 | 55 | |
... | ... | @@ -55,9 +57,11 @@ |
55 | 57 | break; |
56 | 58 | |
57 | 59 | for (i = 0; i < text_len; i++) { |
58 | - while (q > 0 && kmp->pattern[q] != text[i]) | |
60 | + while (q > 0 && kmp->pattern[q] | |
61 | + != (icase ? toupper(text[i]) : text[i])) | |
59 | 62 | q = kmp->prefix_tbl[q - 1]; |
60 | - if (kmp->pattern[q] == text[i]) | |
63 | + if (kmp->pattern[q] | |
64 | + == (icase ? toupper(text[i]) : text[i])) | |
61 | 65 | q++; |
62 | 66 | if (unlikely(q == kmp->pattern_len)) { |
63 | 67 | state->offset = consumed + i + 1; |
64 | 68 | |
65 | 69 | |
66 | 70 | |
67 | 71 | |
68 | 72 | |
... | ... | @@ -72,24 +76,28 @@ |
72 | 76 | } |
73 | 77 | |
74 | 78 | static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len, |
75 | - unsigned int *prefix_tbl) | |
79 | + unsigned int *prefix_tbl, int flags) | |
76 | 80 | { |
77 | 81 | unsigned int k, q; |
82 | + const u8 icase = flags & TS_IGNORECASE; | |
78 | 83 | |
79 | 84 | for (k = 0, q = 1; q < len; q++) { |
80 | - while (k > 0 && pattern[k] != pattern[q]) | |
85 | + while (k > 0 && (icase ? toupper(pattern[k]) : pattern[k]) | |
86 | + != (icase ? toupper(pattern[q]) : pattern[q])) | |
81 | 87 | k = prefix_tbl[k-1]; |
82 | - if (pattern[k] == pattern[q]) | |
88 | + if ((icase ? toupper(pattern[k]) : pattern[k]) | |
89 | + == (icase ? toupper(pattern[q]) : pattern[q])) | |
83 | 90 | k++; |
84 | 91 | prefix_tbl[q] = k; |
85 | 92 | } |
86 | 93 | } |
87 | 94 | |
88 | 95 | static struct ts_config *kmp_init(const void *pattern, unsigned int len, |
89 | - gfp_t gfp_mask) | |
96 | + gfp_t gfp_mask, int flags) | |
90 | 97 | { |
91 | 98 | struct ts_config *conf; |
92 | 99 | struct ts_kmp *kmp; |
100 | + int i; | |
93 | 101 | unsigned int prefix_tbl_len = len * sizeof(unsigned int); |
94 | 102 | size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len; |
95 | 103 | |
96 | 104 | |
97 | 105 | |
... | ... | @@ -97,11 +105,16 @@ |
97 | 105 | if (IS_ERR(conf)) |
98 | 106 | return conf; |
99 | 107 | |
108 | + conf->flags = flags; | |
100 | 109 | kmp = ts_config_priv(conf); |
101 | 110 | kmp->pattern_len = len; |
102 | - compute_prefix_tbl(pattern, len, kmp->prefix_tbl); | |
111 | + compute_prefix_tbl(pattern, len, kmp->prefix_tbl, flags); | |
103 | 112 | kmp->pattern = (u8 *) kmp->prefix_tbl + prefix_tbl_len; |
104 | - memcpy(kmp->pattern, pattern, len); | |
113 | + if (flags & TS_IGNORECASE) | |
114 | + for (i = 0; i < len; i++) | |
115 | + kmp->pattern[i] = toupper(((u8 *)pattern)[i]); | |
116 | + else | |
117 | + memcpy(kmp->pattern, pattern, len); | |
105 | 118 | |
106 | 119 | return conf; |
107 | 120 | } |