diff options
author | Joonwoo Park <joonwpark81@gmail.com> | 2008-07-08 05:38:09 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-08 05:38:09 -0400 |
commit | 2523c3fc2bc9e34c06a71517844d55353f1f904a (patch) | |
tree | ac84b347f87d4a01110c0294ba4452a12db4c60a /lib | |
parent | 3b76d08190e6b420ed3f5534aa99ee29d82d731f (diff) |
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>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ts_kmp.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/lib/ts_kmp.c b/lib/ts_kmp.c index 3ced628cab4b..632f783e65f1 100644 --- a/lib/ts_kmp.c +++ b/lib/ts_kmp.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/types.h> | 34 | #include <linux/types.h> |
35 | #include <linux/string.h> | 35 | #include <linux/string.h> |
36 | #include <linux/ctype.h> | ||
36 | #include <linux/textsearch.h> | 37 | #include <linux/textsearch.h> |
37 | 38 | ||
38 | struct ts_kmp | 39 | struct ts_kmp |
@@ -47,6 +48,7 @@ static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state) | |||
47 | struct ts_kmp *kmp = ts_config_priv(conf); | 48 | struct ts_kmp *kmp = ts_config_priv(conf); |
48 | unsigned int i, q = 0, text_len, consumed = state->offset; | 49 | unsigned int i, q = 0, text_len, consumed = state->offset; |
49 | const u8 *text; | 50 | const u8 *text; |
51 | const int icase = conf->flags & TS_IGNORECASE; | ||
50 | 52 | ||
51 | for (;;) { | 53 | for (;;) { |
52 | text_len = conf->get_next_block(consumed, &text, conf, state); | 54 | text_len = conf->get_next_block(consumed, &text, conf, state); |
@@ -55,9 +57,11 @@ static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state) | |||
55 | break; | 57 | break; |
56 | 58 | ||
57 | for (i = 0; i < text_len; i++) { | 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 | q = kmp->prefix_tbl[q - 1]; | 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 | q++; | 65 | q++; |
62 | if (unlikely(q == kmp->pattern_len)) { | 66 | if (unlikely(q == kmp->pattern_len)) { |
63 | state->offset = consumed + i + 1; | 67 | state->offset = consumed + i + 1; |
@@ -72,24 +76,28 @@ static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state) | |||
72 | } | 76 | } |
73 | 77 | ||
74 | static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len, | 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 | unsigned int k, q; | 81 | unsigned int k, q; |
82 | const u8 icase = flags & TS_IGNORECASE; | ||
78 | 83 | ||
79 | for (k = 0, q = 1; q < len; q++) { | 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 | k = prefix_tbl[k-1]; | 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 | k++; | 90 | k++; |
84 | prefix_tbl[q] = k; | 91 | prefix_tbl[q] = k; |
85 | } | 92 | } |
86 | } | 93 | } |
87 | 94 | ||
88 | static struct ts_config *kmp_init(const void *pattern, unsigned int len, | 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 | struct ts_config *conf; | 98 | struct ts_config *conf; |
92 | struct ts_kmp *kmp; | 99 | struct ts_kmp *kmp; |
100 | int i; | ||
93 | unsigned int prefix_tbl_len = len * sizeof(unsigned int); | 101 | unsigned int prefix_tbl_len = len * sizeof(unsigned int); |
94 | size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len; | 102 | size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len; |
95 | 103 | ||
@@ -97,11 +105,16 @@ static struct ts_config *kmp_init(const void *pattern, unsigned int len, | |||
97 | if (IS_ERR(conf)) | 105 | if (IS_ERR(conf)) |
98 | return conf; | 106 | return conf; |
99 | 107 | ||
108 | conf->flags = flags; | ||
100 | kmp = ts_config_priv(conf); | 109 | kmp = ts_config_priv(conf); |
101 | kmp->pattern_len = len; | 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 | kmp->pattern = (u8 *) kmp->prefix_tbl + prefix_tbl_len; | 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 | return conf; | 119 | return conf; |
107 | } | 120 | } |