2 * Knuth-Morris-Pratt's Substring Search for N given strings
4 * (c) 1999--2005, Robert Spalek <robert@ucw.cz>
5 * (c) 2006, Pavel Charvat <pchar@ucw.cz>
7 * (In fact, the algorithm is usually referred to as Aho-McCorasick,
8 * but that's just an extension of KMP to multiple strings.)
12 * This is not a normal header file, it's a generator of KMP algorithm.
13 * Each time you include it with parameters set in the corresponding
14 * preprocessor macros, it generates KMP structures and functions
15 * with the parameters given. Macros marked with [*] are mandatory.
17 * [*] KMPS_PREFIX(x) macro to add a name prefix (used on all global names
18 * defined by the KMP search generator)
19 * [*] KMPS_KMP_PREFIX(x) prefix used for lib/kmp.h;
20 * more variants of kmp-search can be used for single lib/kmp.h
22 * KMPS_SOURCE user-defined search input (together with KMPS_GET_CHAR);
23 * if unset, the one from lib/kmp.h is used
24 * KMPS_GET_CHAR(kmp,src,s)
26 * KMPS_ADD_CONTROLS add control characters at both ends of the input string
27 * KMPS_MERGE_CONTROLS merge adjacent control characters to a single one
31 * KMPS_INIT(kmp,src,s)
32 * KMPS_EXIT(kmp,src,s)
33 * KMPS_STEP(kmp,src,s)
34 * KMPS_FOUND(kmp,src,s)
35 * KMPS_FOUND_CHAIN(kmp,src,s)
40 #define P(x) KMPS_PREFIX(x)
41 #define KP(x) KMPS_KMP_PREFIX(x)
44 typedef KMPS_SOURCE P(search_source_t);
46 typedef KP(source_t) P(search_source_t);
50 #define KMPS_GET_CHAR(kmp,src,s) (KP(get_char)(kmp, &src, &s->c))
54 struct KP(state) *s; /* current state */
55 struct KP(state) *out; /* output state */
56 # ifdef KMPS_WANT_BEST
57 struct KP(state) *best; /* longest match */
59 KP(char_t) c; /* last character */
60 # ifdef KMPS_ADD_CONTROLS
66 } u; /* user-defined */
71 P(search) (struct KP(struct) *kmp, struct P(search) *s, P(search_source_t) src)
74 # ifdef KMPS_WANT_BEST
77 # ifdef KMPS_ADD_CONTROLS
84 { KMPS_INIT(kmp, src, s); }
86 # ifndef KMPS_ADD_CONTROLS
91 for (struct KP(state) *t = s->s; t && !(s->s = KP(hash_find)(&kmp->hash, t, s->c)); t = t->back);
92 s->s = s->s ? : &kmp->null;
95 { KMPS_STEP(kmp, src, s); }
98 # if defined(KMPS_FOUND) || defined(KMPS_FOUND_CHAIN) || defined(KMPS_WANT_BEST)
99 s->out = s->s->len ? s->s : s->s->next;
102 # ifdef KMPS_WANT_BEST
103 if (s->out->len > s->best->len)
106 #ifdef KMPS_FOUND_CHAIN
107 { KMPS_FOUND_CHAIN(kmp, src, s); }
111 { KMPS_FOUND(kmp, src, s); }
112 while (s->out = s->out->next);
117 # ifdef KMPS_ADD_CONTROLS
122 # ifndef KMPS_ADD_CONTROLS
125 # ifdef KMPS_MERGE_CONTROLS
126 KP(char_t) last_c = s->c;
131 if (!KMPS_GET_CHAR(kmp, src, s))
133 # ifdef KMPS_ADD_CONTROLS
134 if (!KP(is_control)(kmp, s->c))
136 s->c = KP(control)();
145 # ifdef KMPS_MERGE_CONTROLS
146 || (KP(is_control)(kmp, last_c) && KP(is_control)(kmp, s->c))
152 { KMPS_EXIT(kmp, src, s); }
157 P(run) (struct KP(struct) *kmp, P(search_source_t) src)
159 struct P(search) search;
160 P(search)(kmp, &search, src);
165 #undef KMPS_KMP_PREFIX
168 #undef KMPS_ADD_CONTROLS
169 #undef KMPS_MERGE_CONTROLS
174 #undef KMPS_FOUND_CHAIN
176 #undef KMPS_WANT_BEST