1 | /* -*- c-basic-offset: 2 -*- */ |
2 | /* |
3 | Copyright(C) 2015 Brazil |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Lesser General Public |
7 | License version 2.1 as published by the Free Software Foundation. |
8 | |
9 | This library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with this library; if not, write to the Free Software |
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ |
18 | |
19 | #include <string.h> |
20 | |
21 | #include "grn.h" |
22 | #include "grn_db.h" |
23 | #include "grn_ctx_impl.h" |
24 | |
25 | struct _grn_command_input { |
26 | grn_obj *command; |
27 | grn_hash *arguments; |
28 | }; |
29 | |
30 | grn_command_input * |
31 | grn_command_input_open(grn_ctx *ctx, grn_obj *command) |
32 | { |
33 | grn_command_input *input = NULL; |
34 | |
35 | GRN_API_ENTER; |
36 | input = GRN_MALLOC(sizeof(grn_command_input)); |
37 | if (!input) { |
38 | ERR(GRN_NO_MEMORY_AVAILABLE, |
39 | "[command-input] failed to allocate grn_command_input" ); |
40 | goto exit; |
41 | } |
42 | |
43 | input->command = command; |
44 | /* TODO: Allocate by self. */ |
45 | { |
46 | uint32_t n; |
47 | input->arguments = grn_expr_get_vars(ctx, input->command, &n); |
48 | } |
49 | |
50 | exit : |
51 | GRN_API_RETURN(input); |
52 | } |
53 | |
54 | grn_rc |
55 | grn_command_input_close(grn_ctx *ctx, grn_command_input *input) |
56 | { |
57 | GRN_API_ENTER; |
58 | |
59 | /* TODO: Free input->arguments by self. */ |
60 | /* grn_expr_clear_vars(ctx, input->command); */ |
61 | GRN_FREE(input); |
62 | |
63 | GRN_API_RETURN(ctx->rc); |
64 | } |
65 | |
66 | grn_obj * |
67 | grn_command_input_add(grn_ctx *ctx, |
68 | grn_command_input *input, |
69 | const char *name, |
70 | int name_size, |
71 | grn_bool *added) |
72 | { |
73 | grn_obj *argument = NULL; |
74 | /* TODO: Use grn_bool */ |
75 | int internal_added = GRN_FALSE; |
76 | |
77 | GRN_API_ENTER; |
78 | |
79 | if (name_size == -1) { |
80 | name_size = strlen(name); |
81 | } |
82 | if (input->arguments) { |
83 | grn_hash_add(ctx, input->arguments, name, name_size, (void **)&argument, |
84 | &internal_added); |
85 | if (internal_added) { |
86 | GRN_TEXT_INIT(argument, 0); |
87 | } |
88 | } |
89 | if (added) { |
90 | *added = internal_added; |
91 | } |
92 | |
93 | GRN_API_RETURN(argument); |
94 | } |
95 | |
96 | grn_obj * |
97 | grn_command_input_get(grn_ctx *ctx, |
98 | grn_command_input *input, |
99 | const char *name, |
100 | int name_size) |
101 | { |
102 | grn_obj *argument = NULL; |
103 | |
104 | GRN_API_ENTER; |
105 | |
106 | if (name_size == -1) { |
107 | name_size = strlen(name); |
108 | } |
109 | if (input->arguments) { |
110 | grn_hash_get(ctx, input->arguments, name, name_size, (void **)&argument); |
111 | } |
112 | |
113 | GRN_API_RETURN(argument); |
114 | } |
115 | |
116 | grn_obj * |
117 | grn_command_input_at(grn_ctx *ctx, |
118 | grn_command_input *input, |
119 | unsigned int offset) |
120 | { |
121 | grn_obj *argument = NULL; |
122 | |
123 | GRN_API_ENTER; |
124 | if (input->arguments) { |
125 | argument = (grn_obj *)grn_hash_get_value_(ctx, input->arguments, |
126 | offset + 1, NULL); |
127 | } |
128 | GRN_API_RETURN(argument); |
129 | } |
130 | |
131 | grn_obj * |
132 | grn_command_input_get_arguments(grn_ctx *ctx, |
133 | grn_command_input *input) |
134 | { |
135 | GRN_API_ENTER; |
136 | GRN_API_RETURN((grn_obj *)(input->arguments)); |
137 | } |
138 | |
139 | grn_rc |
140 | grn_command_register(grn_ctx *ctx, |
141 | const char *command_name, |
142 | int command_name_size, |
143 | grn_command_run_func *run, |
144 | grn_expr_var *vars, |
145 | unsigned int n_vars, |
146 | void *user_data) |
147 | { |
148 | GRN_API_ENTER; |
149 | |
150 | if (command_name_size == -1) { |
151 | command_name_size = strlen(command_name); |
152 | } |
153 | |
154 | { |
155 | grn_obj *command_object; |
156 | command_object = grn_proc_create(ctx, |
157 | command_name, |
158 | command_name_size, |
159 | GRN_PROC_COMMAND, |
160 | NULL, NULL, NULL, n_vars, vars); |
161 | if (!command_object) { |
162 | GRN_PLUGIN_ERROR(ctx, GRN_COMMAND_ERROR, |
163 | "[command][%.*s] failed to grn_proc_create()" , |
164 | command_name_size, command_name); |
165 | GRN_API_RETURN(ctx->rc); |
166 | } |
167 | |
168 | { |
169 | grn_proc *command = (grn_proc *)command_object; |
170 | command->callbacks.command.run = run; |
171 | command->user_data = user_data; |
172 | } |
173 | } |
174 | |
175 | GRN_API_RETURN(GRN_SUCCESS); |
176 | } |
177 | |
178 | grn_rc |
179 | grn_command_run(grn_ctx *ctx, |
180 | grn_obj *command, |
181 | grn_command_input *input) |
182 | { |
183 | grn_proc *proc; |
184 | |
185 | GRN_API_ENTER; |
186 | |
187 | proc = (grn_proc *)command; |
188 | if (proc->callbacks.command.run) { |
189 | proc->callbacks.command.run(ctx, command, input, proc->user_data); |
190 | } else { |
191 | /* TODO: REMOVE ME. For backward compatibility. */ |
192 | uint32_t stack_curr = ctx->impl->stack_curr; |
193 | grn_proc_call(ctx, command, 0, command); |
194 | if (ctx->impl->stack_curr > stack_curr) { |
195 | grn_ctx_pop(ctx); |
196 | } |
197 | } |
198 | |
199 | GRN_API_RETURN(ctx->rc); |
200 | } |
201 | |
202 | |