save
[protos/libecoli.git] / lib / ecoli_tk.h
1 /*
2  * Copyright (c) 2016, Olivier MATZ <zer0@droids-corp.org>
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *     * Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *     * Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *     * Neither the name of the University of California, Berkeley nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #ifndef ECOLI_TK_
29 #define ECOLI_TK_
30
31 #include <sys/queue.h>
32 #include <sys/types.h>
33 #include <stdio.h>
34
35 #define EC_TK_ENDLIST ((void *)1)
36
37 struct ec_tk;
38 struct ec_parsed_tk;
39 struct ec_strvec;
40 struct ec_keyval;
41
42 /* return 0 on success, else -errno. */
43 typedef int (*ec_tk_build_t)(struct ec_tk *tk);
44
45 typedef struct ec_parsed_tk *(*ec_tk_parse_t)(const struct ec_tk *tk,
46         const struct ec_strvec *strvec);
47 typedef struct ec_completed_tk *(*ec_tk_complete_t)(const struct ec_tk *tk,
48         const struct ec_strvec *strvec);
49 typedef const char * (*ec_tk_desc_t)(const struct ec_tk *);
50 typedef void (*ec_tk_free_priv_t)(struct ec_tk *);
51
52 #define EC_TK_TYPE_REGISTER(t)                                          \
53         static void ec_tk_init_##t(void);                               \
54         static void __attribute__((constructor, used))                  \
55         ec_tk_init_##t(void)                                            \
56         {                                                               \
57                 if (ec_tk_type_register(&t) < 0)                        \
58                         fprintf(stderr, "cannot register %s\n", t.name); \
59         }
60
61 TAILQ_HEAD(ec_tk_type_list, ec_tk_type);
62
63 /**
64  * A structure describing a tk type.
65  */
66 struct ec_tk_type {
67         TAILQ_ENTRY(ec_tk_type) next;  /**< Next in list. */
68         const char *name;              /**< Tk type name. */
69         ec_tk_build_t build; /* (re)build the node, called by generic parse */
70         ec_tk_parse_t parse;
71         ec_tk_complete_t complete;
72         ec_tk_desc_t desc;
73         ec_tk_free_priv_t free_priv;
74 };
75
76 /**
77  * Register a token type.
78  *
79  * @param type
80  *   A pointer to a ec_test structure describing the test
81  *   to be registered.
82  * @return
83  *   0 on success, negative value on error.
84  */
85 int ec_tk_type_register(struct ec_tk_type *type);
86
87 /**
88  * Lookup token type by name
89  *
90  * @param name
91  *   The name of the token type to search.
92  * @return
93  *   The token type if found, or NULL on error.
94  */
95 struct ec_tk_type *ec_tk_type_lookup(const char *name);
96
97 /**
98  * Dump registered log types
99  */
100 void ec_tk_type_dump(FILE *out);
101
102 TAILQ_HEAD(ec_tk_list, ec_tk);
103
104 struct ec_tk {
105         const struct ec_tk_type *type;
106         char *id;
107         char *desc;
108         struct ec_keyval *attrs;
109         /* XXX ensure parent and child are properly set in all nodes */
110         struct ec_tk *parent;
111         unsigned int refcnt;
112 #define EC_TK_F_BUILT 0x0001 /** set if configuration is built */
113         unsigned int flags;
114
115         TAILQ_ENTRY(ec_tk) next;
116         struct ec_tk_list children;
117 };
118
119 struct ec_tk *ec_tk_new(const char *id, const struct ec_tk_type *type,
120         size_t priv_size);
121 void ec_tk_free(struct ec_tk *tk);
122
123 /* XXX add more accessors */
124 struct ec_keyval *ec_tk_attrs(const struct ec_tk *tk);
125 struct ec_tk *ec_tk_parent(const struct ec_tk *tk);
126 const char *ec_tk_id(const struct ec_tk *tk);
127 const char *ec_tk_desc(const struct ec_tk *tk);
128
129 void ec_tk_dump(FILE *out, const struct ec_tk *tk);
130 struct ec_tk *ec_tk_find(struct ec_tk *tk, const char *id);
131
132 /* XXX split this file ? */
133
134 TAILQ_HEAD(ec_parsed_tk_list, ec_parsed_tk);
135
136 /*
137   tk == NULL + empty children list means "no match"
138 */
139 struct ec_parsed_tk {
140         TAILQ_ENTRY(ec_parsed_tk) next;
141         struct ec_parsed_tk_list children;
142         const struct ec_tk *tk;
143         struct ec_strvec *strvec;
144 };
145
146 struct ec_parsed_tk *ec_parsed_tk_new(void);
147 void ec_parsed_tk_free(struct ec_parsed_tk *parsed_tk);
148 struct ec_tk *ec_tk_clone(struct ec_tk *tk);
149 void ec_parsed_tk_free_children(struct ec_parsed_tk *parsed_tk);
150
151 const struct ec_strvec *ec_parsed_tk_strvec(
152         const struct ec_parsed_tk *parsed_tk);
153
154 void ec_parsed_tk_set_match(struct ec_parsed_tk *parsed_tk,
155         const struct ec_tk *tk, struct ec_strvec *strvec);
156
157 /* XXX we could use a cache to store possible completions or match: the
158  * cache would be per-node, and would be reset for each call to parse()
159  * or complete() ? */
160 /* a NULL return value is an error, with errno set
161   ENOTSUP: no ->parse() operation
162 */
163 struct ec_parsed_tk *ec_tk_parse(struct ec_tk *tk, const char *str);
164
165 /* mostly internal to tokens */
166 /* XXX it should not reset cache
167  * ... not sure... it is used by tests */
168 struct ec_parsed_tk *ec_tk_parse_tokens(struct ec_tk *tk,
169         const struct ec_strvec *strvec);
170
171 void ec_parsed_tk_add_child(struct ec_parsed_tk *parsed_tk,
172         struct ec_parsed_tk *child);
173 void ec_parsed_tk_del_child(struct ec_parsed_tk *parsed_tk,
174         struct ec_parsed_tk *child);
175 void ec_parsed_tk_dump(FILE *out, const struct ec_parsed_tk *parsed_tk);
176
177 struct ec_parsed_tk *ec_parsed_tk_find_first(struct ec_parsed_tk *parsed_tk,
178         const char *id);
179
180 const char *ec_parsed_tk_to_string(const struct ec_parsed_tk *parsed_tk);
181 size_t ec_parsed_tk_len(const struct ec_parsed_tk *parsed_tk);
182 size_t ec_parsed_tk_matches(const struct ec_parsed_tk *parsed_tk);
183
184 struct ec_completed_tk_elt {
185         TAILQ_ENTRY(ec_completed_tk_elt) next;
186         const struct ec_tk *tk;
187         char *add;
188 };
189
190 TAILQ_HEAD(ec_completed_tk_elt_list, ec_completed_tk_elt);
191
192
193 struct ec_completed_tk {
194         struct ec_completed_tk_elt_list elts;
195         unsigned count;
196         unsigned count_match;
197         char *smallest_start;
198 };
199
200 /*
201  * return a completed_tk object filled with elts
202  * return NULL on error (nomem?)
203  */
204 struct ec_completed_tk *ec_tk_complete(struct ec_tk *tk,
205         const char *str);
206 struct ec_completed_tk *ec_tk_complete_tokens(struct ec_tk *tk,
207         const struct ec_strvec *strvec);
208 struct ec_completed_tk *ec_completed_tk_new(void);
209 struct ec_completed_tk_elt *ec_completed_tk_elt_new(const struct ec_tk *tk,
210         const char *add);
211 void ec_completed_tk_add_elt(struct ec_completed_tk *completed_tk,
212         struct ec_completed_tk_elt *elt);
213 void ec_completed_tk_elt_free(struct ec_completed_tk_elt *elt);
214 void ec_completed_tk_merge(struct ec_completed_tk *completed_tk1,
215         struct ec_completed_tk *completed_tk2);
216 void ec_completed_tk_free(struct ec_completed_tk *completed_tk);
217 void ec_completed_tk_dump(FILE *out,
218         const struct ec_completed_tk *completed_tk);
219 struct ec_completed_tk *ec_tk_default_complete(const struct ec_tk *gen_tk,
220         const struct ec_strvec *strvec);
221
222 /* cannot return NULL */
223 const char *ec_completed_tk_smallest_start(
224         const struct ec_completed_tk *completed_tk);
225
226 enum ec_completed_tk_filter_flags {
227         EC_MATCH = 1,
228         EC_NO_MATCH = 2,
229 };
230
231 unsigned int ec_completed_tk_count(
232         const struct ec_completed_tk *completed_tk,
233         enum ec_completed_tk_filter_flags flags);
234
235 struct ec_completed_tk_iter {
236         enum ec_completed_tk_filter_flags flags;
237         const struct ec_completed_tk *completed_tk;
238         const struct ec_completed_tk_elt *cur;
239 };
240
241 struct ec_completed_tk_iter *
242 ec_completed_tk_iter_new(struct ec_completed_tk *completed_tk,
243         enum ec_completed_tk_filter_flags flags);
244
245 const struct ec_completed_tk_elt *ec_completed_tk_iter_next(
246         struct ec_completed_tk_iter *iter);
247
248 void ec_completed_tk_iter_free(struct ec_completed_tk_iter *iter);
249
250
251 #endif