save
[protos/libecoli.git] / lib / ecoli_tk_option.c
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 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <assert.h>
32 #include <stdarg.h>
33
34 #include <ecoli_malloc.h>
35 #include <ecoli_log.h>
36 #include <ecoli_tk.h>
37 #include <ecoli_tk_option.h>
38 #include <ecoli_tk_str.h>
39 #include <ecoli_test.h>
40
41 static struct ec_parsed_tk *ec_tk_option_parse(const struct ec_tk *gen_tk,
42         const char *str)
43 {
44         struct ec_tk_option *tk = (struct ec_tk_option *)gen_tk;
45         struct ec_parsed_tk *parsed_tk, *child_parsed_tk;
46
47         parsed_tk = ec_parsed_tk_new(gen_tk);
48         if (parsed_tk == NULL)
49                 return NULL;
50
51         child_parsed_tk = ec_tk_parse(tk->child, str);
52         if (child_parsed_tk != NULL) {
53                 ec_parsed_tk_add_child(parsed_tk, child_parsed_tk);
54                 parsed_tk->str = ec_strndup(child_parsed_tk->str,
55                         strlen(child_parsed_tk->str));
56         } else {
57                 parsed_tk->str = ec_strdup("");
58         }
59
60         return parsed_tk;
61 }
62
63 static struct ec_completed_tk *ec_tk_option_complete(const struct ec_tk *gen_tk,
64         const char *str)
65 {
66         struct ec_tk_option *tk = (struct ec_tk_option *)gen_tk;
67
68         return ec_tk_complete(tk->child, str);
69 }
70
71 static void ec_tk_option_free_priv(struct ec_tk *gen_tk)
72 {
73         struct ec_tk_option *tk = (struct ec_tk_option *)gen_tk;
74
75         ec_tk_free(tk->child);
76 }
77
78 static struct ec_tk_ops ec_tk_option_ops = {
79         .parse = ec_tk_option_parse,
80         .complete = ec_tk_option_complete,
81         .free_priv = ec_tk_option_free_priv,
82 };
83
84 struct ec_tk *ec_tk_option_new(const char *id, struct ec_tk *child)
85 {
86         struct ec_tk_option *tk = NULL;
87
88         if (child == NULL)
89                 return NULL;
90
91         tk = (struct ec_tk_option *)ec_tk_new(id, &ec_tk_option_ops,
92                 sizeof(*tk));
93         if (tk == NULL)
94                 return NULL;
95
96         tk->child = child;
97
98         return &tk->gen;
99 }
100
101 static int ec_tk_option_testcase(void)
102 {
103         struct ec_tk *tk;
104         int ret = 0;
105
106         tk = ec_tk_option_new(NULL, ec_tk_str_new(NULL, "foo"));
107         if (tk == NULL) {
108                 ec_log(EC_LOG_ERR, "cannot create tk\n");
109                 return -1;
110         }
111         ret |= EC_TEST_CHECK_TK_PARSE(tk, "", "");
112         ret |= EC_TEST_CHECK_TK_PARSE(tk, "foo", "foo");
113         ret |= EC_TEST_CHECK_TK_PARSE(tk, "bar", "");
114         ec_tk_free(tk);
115
116         /* test completion */
117         tk = ec_tk_option_new(NULL, ec_tk_str_new(NULL, "foo"));
118         if (tk == NULL) {
119                 ec_log(EC_LOG_ERR, "cannot create tk\n");
120                 return -1;
121         }
122         ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "", "foo");
123         ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "f", "oo");
124         ret |= EC_TEST_CHECK_TK_COMPLETE(tk, "b", "");
125         ret |= EC_TEST_CHECK_TK_COMPLETE_LIST(tk, "",
126                 "foo", EC_TK_ENDLIST);
127         ec_tk_free(tk);
128
129         return ret;
130 }
131
132 static struct ec_test ec_tk_option_test = {
133         .name = "tk_option",
134         .test = ec_tk_option_testcase,
135 };
136
137 EC_REGISTER_TEST(ec_tk_option_test);