ts_kmp.c (05668381140309088443bf5dc53add4104610fbb) | ts_kmp.c (2523c3fc2bc9e34c06a71517844d55353f1f904a) |
---|---|
1/* 2 * lib/ts_kmp.c Knuth-Morris-Pratt text search implementation 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 19 unchanged lines hidden (view full) --- 28 * [1] Cormen, Leiserson, Rivest, Stein 29 * Introdcution to Algorithms, 2nd Edition, MIT Press 30 * [2] See finite automation theory 31 */ 32 33#include <linux/module.h> 34#include <linux/types.h> 35#include <linux/string.h> | 1/* 2 * lib/ts_kmp.c Knuth-Morris-Pratt text search implementation 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * --- 19 unchanged lines hidden (view full) --- 28 * [1] Cormen, Leiserson, Rivest, Stein 29 * Introdcution to Algorithms, 2nd Edition, MIT Press 30 * [2] See finite automation theory 31 */ 32 33#include <linux/module.h> 34#include <linux/types.h> 35#include <linux/string.h> |
36#include <linux/ctype.h> |
|
36#include <linux/textsearch.h> 37 38struct ts_kmp 39{ 40 u8 * pattern; 41 unsigned int pattern_len; 42 unsigned int prefix_tbl[0]; 43}; 44 45static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state) 46{ 47 struct ts_kmp *kmp = ts_config_priv(conf); 48 unsigned int i, q = 0, text_len, consumed = state->offset; 49 const u8 *text; | 37#include <linux/textsearch.h> 38 39struct ts_kmp 40{ 41 u8 * pattern; 42 unsigned int pattern_len; 43 unsigned int prefix_tbl[0]; 44}; 45 46static unsigned int kmp_find(struct ts_config *conf, struct ts_state *state) 47{ 48 struct ts_kmp *kmp = ts_config_priv(conf); 49 unsigned int i, q = 0, text_len, consumed = state->offset; 50 const u8 *text; |
51 const int icase = conf->flags & TS_IGNORECASE; |
|
50 51 for (;;) { 52 text_len = conf->get_next_block(consumed, &text, conf, state); 53 54 if (unlikely(text_len == 0)) 55 break; 56 57 for (i = 0; i < text_len; i++) { | 52 53 for (;;) { 54 text_len = conf->get_next_block(consumed, &text, conf, state); 55 56 if (unlikely(text_len == 0)) 57 break; 58 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++; 62 if (unlikely(q == kmp->pattern_len)) { 63 state->offset = consumed + i + 1; 64 return state->offset - kmp->pattern_len; 65 } 66 } 67 68 consumed += text_len; 69 } 70 71 return UINT_MAX; 72} 73 74static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len, | 65 q++; 66 if (unlikely(q == kmp->pattern_len)) { 67 state->offset = consumed + i + 1; 68 return state->offset - kmp->pattern_len; 69 } 70 } 71 72 consumed += text_len; 73 } 74 75 return UINT_MAX; 76} 77 78static inline void compute_prefix_tbl(const u8 *pattern, unsigned int len, |
75 unsigned int *prefix_tbl) | 79 unsigned int *prefix_tbl, int flags) |
76{ 77 unsigned int k, q; | 80{ 81 unsigned int k, q; |
82 const u8 icase = flags & TS_IGNORECASE; |
|
78 79 for (k = 0, q = 1; q < len; q++) { | 83 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++; 84 prefix_tbl[q] = k; 85 } 86} 87 88static struct ts_config *kmp_init(const void *pattern, unsigned int len, | 90 k++; 91 prefix_tbl[q] = k; 92 } 93} 94 95static struct ts_config *kmp_init(const void *pattern, unsigned int len, |
89 gfp_t gfp_mask) | 96 gfp_t gfp_mask, int flags) |
90{ 91 struct ts_config *conf; 92 struct ts_kmp *kmp; | 97{ 98 struct ts_config *conf; 99 struct ts_kmp *kmp; |
100 int i; |
|
93 unsigned int prefix_tbl_len = len * sizeof(unsigned int); 94 size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len; 95 96 conf = alloc_ts_config(priv_size, gfp_mask); 97 if (IS_ERR(conf)) 98 return conf; 99 | 101 unsigned int prefix_tbl_len = len * sizeof(unsigned int); 102 size_t priv_size = sizeof(*kmp) + len + prefix_tbl_len; 103 104 conf = alloc_ts_config(priv_size, gfp_mask); 105 if (IS_ERR(conf)) 106 return conf; 107 |
108 conf->flags = flags; |
|
100 kmp = ts_config_priv(conf); 101 kmp->pattern_len = len; | 109 kmp = ts_config_priv(conf); 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 106 return conf; 107} 108 109static void *kmp_get_pattern(struct ts_config *conf) 110{ 111 struct ts_kmp *kmp = ts_config_priv(conf); 112 return kmp->pattern; --- 32 unchanged lines hidden --- | 118 119 return conf; 120} 121 122static void *kmp_get_pattern(struct ts_config *conf) 123{ 124 struct ts_kmp *kmp = ts_config_priv(conf); 125 return kmp->pattern; --- 32 unchanged lines hidden --- |