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