Libecoli 0.11.1
Extensible COmmand LIne library
Loading...
Searching...
No Matches
node_bool_tuple.c
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2016, Olivier MATZ <zer0@droids-corp.org>
3 */
4
5#include <assert.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include <ecoli.h>
11
12EC_LOG_TYPE_REGISTER(node_bool_tuple);
13
14enum bool_tuple_state {
15 BT_EMPTY,
16 BT_OPEN,
17 BT_BOOL,
18 BT_COMMA,
19 BT_END,
20 BT_FAIL,
21};
22
23/* Check if input matches a bool tuple like this: "(true,false,true)". On success, *state is set to
24 * BT_END. If parsing is incomplete or fails, set the *state to something else, and return the
25 * pointer to the incomplete or failing token.
26 */
27static const char *parse_bool_tuple(const char *input, enum bool_tuple_state *state)
28{
29 *state = BT_EMPTY;
30 if (*input == '\0')
31 return input;
32
33 if (*input != '(') {
34 *state = BT_FAIL;
35 return input;
36 }
37 input++;
38 *state = BT_OPEN;
39
40 if (*input == ')') {
41 *state = BT_END;
42 input++;
43 if (*input != '\0') {
44 *state = BT_FAIL;
45 return input;
46 }
47
48 return input;
49 }
50
51 while (1) {
52 if (ec_str_startswith(input, "true")) {
53 input += 4;
54 } else if (ec_str_startswith(input, "false")) {
55 input += 5;
56 } else {
57 if (!ec_str_startswith("true", input) && !ec_str_startswith("false", input))
58 *state = BT_FAIL;
59 return input;
60 }
61
62 *state = BT_BOOL;
63 if (*input == '\0')
64 return input;
65
66 if (*input == ')') {
67 *state = BT_END;
68 input++;
69 if (*input != '\0') {
70 *state = BT_FAIL;
71 return input;
72 }
73 return input;
74 }
75
76 if (*input != ',') {
77 *state = BT_FAIL;
78 return input;
79 }
80
81 input++;
82 *state = BT_COMMA;
83 }
84}
85
86static int ec_node_bool_tuple_parse(
87 const struct ec_node *node,
88 struct ec_pnode *pstate,
89 const struct ec_strvec *strvec
90)
91{
92 enum bool_tuple_state state;
93 const char *input;
94
95 (void)node;
96 (void)pstate;
97
98 if (ec_strvec_len(strvec) == 0)
99 return EC_PARSE_NOMATCH;
100
101 input = ec_strvec_val(strvec, 0);
102 parse_bool_tuple(input, &state);
103
104 if (state != BT_END)
105 return EC_PARSE_NOMATCH;
106
107 return 1;
108}
109
110static int ec_node_bool_tuple_complete(
111 const struct ec_node *node,
112 struct ec_comp *comp,
113 const struct ec_strvec *strvec
114)
115{
116 struct ec_comp_item *item = NULL;
117 const char *false_str = "false";
118 const char *true_str = "true";
119 enum bool_tuple_state state;
120 char *comp_str = NULL;
121 char *disp_str = NULL;
122 const char *incomplete;
123 const char *input;
124 int ret;
125
126 if (ec_strvec_len(strvec) != 1)
127 return 0;
128
129 input = ec_strvec_val(strvec, 0);
130 incomplete = parse_bool_tuple(input, &state);
131
132 switch (state) {
133 case BT_EMPTY:
134 if (asprintf(&comp_str, "%s(", input) < 0)
135 goto fail;
136 if (asprintf(&disp_str, "(") < 0)
137 goto fail;
138 item = ec_comp_add_item(comp, node, EC_COMP_PARTIAL, input, comp_str);
139 if (item == NULL)
140 goto fail;
141 if (ec_comp_item_set_display(item, disp_str) < 0)
142 goto fail;
143 break;
144 case BT_OPEN:
145 if (incomplete[0] == '\0') {
146 if (asprintf(&comp_str, "%s)", input) < 0)
147 goto fail;
148 if (asprintf(&disp_str, ")") < 0)
149 goto fail;
150 item = ec_comp_add_item(comp, node, EC_COMP_FULL, input, comp_str);
151 if (item == NULL)
152 goto fail;
153 if (ec_comp_item_set_display(item, disp_str) < 0)
154 goto fail;
155 free(comp_str);
156 comp_str = NULL;
157 free(disp_str);
158 disp_str = NULL;
159 }
160 /* fallthrough */
161 case BT_COMMA:
162 if (incomplete[0] == 't' || incomplete[0] == '\0') {
163 if (asprintf(&comp_str, "%s%s", input, &true_str[strlen(incomplete)]) < 0)
164 goto fail;
165 if (asprintf(&disp_str, "true") < 0)
166 goto fail;
167 item = ec_comp_add_item(comp, node, EC_COMP_PARTIAL, input, comp_str);
168 if (item == NULL)
169 goto fail;
170 if (ec_comp_item_set_display(item, disp_str) < 0)
171 goto fail;
172 free(comp_str);
173 comp_str = NULL;
174 free(disp_str);
175 disp_str = NULL;
176 }
177 if (incomplete[0] == 'f' || incomplete[0] == '\0') {
178 if (asprintf(&comp_str, "%s%s", input, &false_str[strlen(incomplete)]) < 0)
179 goto fail;
180 if (asprintf(&disp_str, "false") < 0)
181 goto fail;
182 item = ec_comp_add_item(comp, node, EC_COMP_PARTIAL, input, comp_str);
183 if (item == NULL)
184 goto fail;
185 if (ec_comp_item_set_display(item, disp_str) < 0)
186 goto fail;
187 free(comp_str);
188 comp_str = NULL;
189 free(disp_str);
190 disp_str = NULL;
191 }
192 break;
193 case BT_BOOL:
194 if (asprintf(&comp_str, "%s,", input) < 0)
195 goto fail;
196 if (asprintf(&disp_str, ",") < 0)
197 goto fail;
198 item = ec_comp_add_item(comp, node, EC_COMP_PARTIAL, input, comp_str);
199 if (item == NULL)
200 goto fail;
201 if (ec_comp_item_set_display(item, disp_str) < 0)
202 goto fail;
203 if (asprintf(&comp_str, "%s)", input) < 0)
204 goto fail;
205 if (asprintf(&disp_str, ")") < 0)
206 goto fail;
207 item = ec_comp_add_item(comp, node, EC_COMP_PARTIAL, input, comp_str);
208 if (item == NULL)
209 goto fail;
210 if (ec_comp_item_set_display(item, disp_str) < 0)
211 goto fail;
212 break;
213 case BT_END:
214 item = ec_comp_add_item(comp, node, EC_COMP_FULL, input, input);
215 if (item == NULL)
216 goto fail;
217 break;
218 default:
219 break;
220 }
221
222 ret = 0;
223out:
224 free(comp_str);
225 free(disp_str);
226
227 return ret;
228
229fail:
230 ret = -1;
231 goto out;
232}
233
234static struct ec_node_type ec_node_bool_tuple_type = {
235 .name = "bool_tuple",
236 .parse = ec_node_bool_tuple_parse,
237 .complete = ec_node_bool_tuple_complete,
238};
239
240EC_NODE_TYPE_REGISTER(ec_node_bool_tuple_type);
int ec_comp_item_set_display(struct ec_comp_item *item, const char *display)
struct ec_comp * ec_comp(void)
struct ec_comp_item * ec_comp_add_item(struct ec_comp *comp, const struct ec_node *node, enum ec_comp_type type, const char *current, const char *full)
@ EC_COMP_FULL
Definition complete.h:49
@ EC_COMP_PARTIAL
Definition complete.h:50
#define EC_LOG_TYPE_REGISTER(name)
Definition log.h:69
struct ec_node * ec_node(const char *typename, const char *id)
#define EC_NODE_TYPE_REGISTER(t)
Definition node.h:88
#define EC_PARSE_NOMATCH
Definition parse.h:145
struct ec_pnode * ec_pnode(const struct ec_node *node)
int ec_str_startswith(const char *s, const char *beginning)
const char * ec_strvec_val(const struct ec_strvec *strvec, size_t idx)
struct ec_strvec * ec_strvec(void)
size_t ec_strvec_len(const struct ec_strvec *strvec)