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
25struct _grn_command_input {
26 grn_obj *command;
27 grn_hash *arguments;
28};
29
30grn_command_input *
31grn_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
50exit :
51 GRN_API_RETURN(input);
52}
53
54grn_rc
55grn_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
66grn_obj *
67grn_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
96grn_obj *
97grn_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
116grn_obj *
117grn_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
131grn_obj *
132grn_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
139grn_rc
140grn_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
178grn_rc
179grn_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