diff options
Diffstat (limited to 'lib/ts_kmp.c')
| -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 | } |
