1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef __LINUX_TEXTSEARCH_H
3 #define __LINUX_TEXTSEARCH_H
4
5 #include <linux/types.h>
6 #include <linux/list.h>
7 #include <linux/kernel.h>
8 #include <linux/err.h>
9 #include <linux/slab.h>
10
11 struct module;
12
13 struct ts_config;
14
15 #define TS_AUTOLOAD 1 /* Automatically load textsearch modules when needed */
16 #define TS_IGNORECASE 2 /* Searches string case insensitively */
17
18 /**
19 * struct ts_state - search state
20 * @offset: offset for next match
21 * @cb: control buffer, for persistent variables of get_next_block()
22 */
23 struct ts_state
24 {
25 unsigned int offset;
26 char cb[48];
27 };
28
29 /**
30 * struct ts_ops - search module operations
31 * @name: name of search algorithm
32 * @init: initialization function to prepare a search
33 * @find: find the next occurrence of the pattern
34 * @destroy: destroy algorithm specific parts of a search configuration
35 * @get_pattern: return head of pattern
36 * @get_pattern_len: return length of pattern
37 * @owner: module reference to algorithm
38 * @list: list to search
39 */
40 struct ts_ops
41 {
42 const char *name;
43 struct ts_config * (*init)(const void *, unsigned int, gfp_t, int);
44 unsigned int (*find)(struct ts_config *,
45 struct ts_state *);
46 void (*destroy)(struct ts_config *);
47 void * (*get_pattern)(struct ts_config *);
48 unsigned int (*get_pattern_len)(struct ts_config *);
49 struct module *owner;
50 struct list_head list;
51 };
52
53 /**
54 * struct ts_config - search configuration
55 * @ops: operations of chosen algorithm
56 * @flags: flags
57 * @get_next_block: callback to fetch the next block to search in
58 * @finish: callback to finalize a search
59 */
60 struct ts_config
61 {
62 struct ts_ops *ops;
63 int flags;
64
65 /**
66 * @get_next_block: fetch next block of data
67 * @consumed: number of bytes consumed by the caller
68 * @dst: destination buffer
69 * @conf: search configuration
70 * @state: search state
71 *
72 * Called repeatedly until 0 is returned. Must assign the
73 * head of the next block of data to &*dst and return the length
74 * of the block or 0 if at the end. consumed == 0 indicates
75 * a new search. May store/read persistent values in state->cb.
76 */
77 unsigned int (*get_next_block)(unsigned int consumed,
78 const u8 **dst,
79 struct ts_config *conf,
80 struct ts_state *state);
81
82 /**
83 * @finish: finalize/clean a series of get_next_block() calls
84 * @conf: search configuration
85 * @state: search state
86 *
87 * Called after the last use of get_next_block(), may be used
88 * to cleanup any leftovers.
89 */
90 void (*finish)(struct ts_config *conf,
91 struct ts_state *state);
92 };
93
94 /**
95 * textsearch_next - continue searching for a pattern
96 * @conf: search configuration
97 * @state: search state
98 *
99 * Continues a search looking for more occurrences of the pattern.
100 * textsearch_find() must be called to find the first occurrence
101 * in order to reset the state.
102 *
103 * Returns the position of the next occurrence of the pattern or
104 * UINT_MAX if not match was found.
105 */
textsearch_next(struct ts_config * conf,struct ts_state * state)106 static inline unsigned int textsearch_next(struct ts_config *conf,
107 struct ts_state *state)
108 {
109 unsigned int ret = conf->ops->find(conf, state);
110
111 if (conf->finish)
112 conf->finish(conf, state);
113
114 return ret;
115 }
116
117 /**
118 * textsearch_find - start searching for a pattern
119 * @conf: search configuration
120 * @state: search state
121 *
122 * Returns the position of first occurrence of the pattern or
123 * UINT_MAX if no match was found.
124 */
textsearch_find(struct ts_config * conf,struct ts_state * state)125 static inline unsigned int textsearch_find(struct ts_config *conf,
126 struct ts_state *state)
127 {
128 state->offset = 0;
129 return textsearch_next(conf, state);
130 }
131
132 /**
133 * textsearch_get_pattern - return head of the pattern
134 * @conf: search configuration
135 */
textsearch_get_pattern(struct ts_config * conf)136 static inline void *textsearch_get_pattern(struct ts_config *conf)
137 {
138 return conf->ops->get_pattern(conf);
139 }
140
141 /**
142 * textsearch_get_pattern_len - return length of the pattern
143 * @conf: search configuration
144 */
textsearch_get_pattern_len(struct ts_config * conf)145 static inline unsigned int textsearch_get_pattern_len(struct ts_config *conf)
146 {
147 return conf->ops->get_pattern_len(conf);
148 }
149
150 extern int textsearch_register(struct ts_ops *);
151 extern int textsearch_unregister(struct ts_ops *);
152 extern struct ts_config *textsearch_prepare(const char *, const void *,
153 unsigned int, gfp_t, int);
154 extern void textsearch_destroy(struct ts_config *conf);
155 extern unsigned int textsearch_find_continuous(struct ts_config *,
156 struct ts_state *,
157 const void *, unsigned int);
158
159
160 #define TS_PRIV_ALIGNTO 8
161 #define TS_PRIV_ALIGN(len) (((len) + TS_PRIV_ALIGNTO-1) & ~(TS_PRIV_ALIGNTO-1))
162
alloc_ts_config(size_t payload,gfp_t gfp_mask)163 static inline struct ts_config *alloc_ts_config(size_t payload,
164 gfp_t gfp_mask)
165 {
166 struct ts_config *conf;
167
168 conf = kzalloc(TS_PRIV_ALIGN(sizeof(*conf)) + payload, gfp_mask);
169 if (conf == NULL)
170 return ERR_PTR(-ENOMEM);
171
172 return conf;
173 }
174
ts_config_priv(struct ts_config * conf)175 static inline void *ts_config_priv(struct ts_config *conf)
176 {
177 return ((u8 *) conf + TS_PRIV_ALIGN(sizeof(struct ts_config)));
178 }
179
180 #endif
181