1 /* -*- c-basic-offset: 2 -*- */
2 /*
3 Copyright(C) 2014-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-1335 USA
17 */
18
19 #include "../grn_ctx_impl.h"
20
21 #ifdef GRN_WITH_MRUBY
22 #include <mruby.h>
23 #include <mruby/class.h>
24 #include <mruby/data.h>
25 #include <mruby/string.h>
26 #include <mruby/hash.h>
27 #include <mruby/variable.h>
28
29 #include "mrb_ctx.h"
30 #include "mrb_bulk.h"
31 #include "mrb_table_cursor.h"
32
33 #include "mrb_converter.h"
34 #include "mrb_options.h"
35
36 static struct mrb_data_type mrb_grn_table_cursor_type = {
37 "Groonga::TableCursor",
38 NULL
39 };
40
41 static mrb_value
mrb_grn_table_cursor_class_open_raw(mrb_state * mrb,mrb_value klass)42 mrb_grn_table_cursor_class_open_raw(mrb_state *mrb, mrb_value klass)
43 {
44 grn_ctx *ctx = (grn_ctx *)mrb->ud;
45 mrb_value mrb_table;
46 mrb_value mrb_options = mrb_nil_value();
47 grn_table_cursor *table_cursor;
48 grn_obj *table;
49 void *min = NULL;
50 unsigned int min_size = 0;
51 grn_mrb_value_to_raw_data_buffer min_buffer;
52 void *max = NULL;
53 unsigned int max_size = 0;
54 grn_mrb_value_to_raw_data_buffer max_buffer;
55 int offset = 0;
56 int limit = -1;
57 int flags = 0;
58
59 mrb_get_args(mrb, "o|H", &mrb_table, &mrb_options);
60
61 table = DATA_PTR(mrb_table);
62 grn_mrb_value_to_raw_data_buffer_init(mrb, &min_buffer);
63 grn_mrb_value_to_raw_data_buffer_init(mrb, &max_buffer);
64 if (!mrb_nil_p(mrb_options)) {
65 grn_id key_domain_id;
66 mrb_value mrb_min;
67 mrb_value mrb_max;
68 mrb_value mrb_flags;
69
70 if (table->header.type == GRN_DB) {
71 key_domain_id = GRN_DB_SHORT_TEXT;
72 } else {
73 key_domain_id = table->header.domain;
74 }
75
76 mrb_min = grn_mrb_options_get_lit(mrb, mrb_options, "min");
77 grn_mrb_value_to_raw_data(mrb, "min", mrb_min,
78 key_domain_id, &min_buffer, &min, &min_size);
79
80 mrb_max = grn_mrb_options_get_lit(mrb, mrb_options, "max");
81 grn_mrb_value_to_raw_data(mrb, "max", mrb_max,
82 key_domain_id, &max_buffer, &max, &max_size);
83
84 mrb_flags = grn_mrb_options_get_lit(mrb, mrb_options, "flags");
85 if (!mrb_nil_p(mrb_flags)) {
86 flags = mrb_fixnum(mrb_flags);
87 }
88 }
89 table_cursor = grn_table_cursor_open(ctx, table,
90 min, min_size,
91 max, max_size,
92 offset, limit, flags);
93 grn_mrb_value_to_raw_data_buffer_fin(mrb, &min_buffer);
94 grn_mrb_value_to_raw_data_buffer_fin(mrb, &max_buffer);
95 grn_mrb_ctx_check(mrb);
96
97 {
98 mrb_value mrb_table_cursor;
99 mrb_table_cursor = mrb_funcall(mrb, klass,
100 "new", 1, mrb_cptr_value(mrb, table_cursor));
101 mrb_iv_set(mrb, mrb_table_cursor, mrb_intern_lit(mrb, "@table"), mrb_table);
102 return mrb_table_cursor;
103 }
104 }
105
106 static mrb_value
mrb_grn_table_cursor_initialize(mrb_state * mrb,mrb_value self)107 mrb_grn_table_cursor_initialize(mrb_state *mrb, mrb_value self)
108 {
109 mrb_value mrb_table_cursor_ptr;
110
111 mrb_get_args(mrb, "o", &mrb_table_cursor_ptr);
112 DATA_TYPE(self) = &mrb_grn_table_cursor_type;
113 DATA_PTR(self) = mrb_cptr(mrb_table_cursor_ptr);
114
115 return self;
116 }
117
118 static mrb_value
mrb_grn_table_cursor_close(mrb_state * mrb,mrb_value self)119 mrb_grn_table_cursor_close(mrb_state *mrb, mrb_value self)
120 {
121 grn_ctx *ctx = (grn_ctx *)mrb->ud;
122 grn_table_cursor *table_cursor;
123
124 table_cursor = DATA_PTR(self);
125 if (table_cursor) {
126 DATA_PTR(self) = NULL;
127 grn_table_cursor_close(ctx, table_cursor);
128 grn_mrb_ctx_check(mrb);
129 }
130
131 return mrb_nil_value();
132 }
133
134 static mrb_value
mrb_grn_table_cursor_next(mrb_state * mrb,mrb_value self)135 mrb_grn_table_cursor_next(mrb_state *mrb, mrb_value self)
136 {
137 grn_ctx *ctx = (grn_ctx *)mrb->ud;
138 grn_id id;
139
140 id = grn_table_cursor_next(ctx, DATA_PTR(self));
141 grn_mrb_ctx_check(mrb);
142
143 return mrb_fixnum_value(id);
144 }
145
146 static mrb_value
mrb_grn_table_cursor_count(mrb_state * mrb,mrb_value self)147 mrb_grn_table_cursor_count(mrb_state *mrb, mrb_value self)
148 {
149 grn_ctx *ctx = (grn_ctx *)mrb->ud;
150 int n_records = 0;
151
152 while (grn_table_cursor_next(ctx, DATA_PTR(self)) != GRN_ID_NIL) {
153 n_records++;
154 }
155
156 return mrb_fixnum_value(n_records);
157 }
158
159 static mrb_value
mrb_grn_table_cursor_get_key(mrb_state * mrb,mrb_value self)160 mrb_grn_table_cursor_get_key(mrb_state *mrb, mrb_value self)
161 {
162 grn_ctx *ctx = (grn_ctx *)mrb->ud;
163 mrb_value mrb_table;
164 grn_obj *table;
165 grn_id domain;
166 void *key;
167 int key_size;
168
169 mrb_table = mrb_iv_get(mrb, self, mrb_intern_lit(mrb, "@table"));
170 table = DATA_PTR(mrb_table);
171 if (table->header.type == GRN_DB) {
172 domain = GRN_DB_SHORT_TEXT;
173 } else {
174 domain = table->header.domain;
175 }
176 key_size = grn_table_cursor_get_key(ctx, DATA_PTR(self), &key);
177
178 return grn_mrb_value_from_raw_data(mrb, domain, key, key_size);
179 }
180
181 void
grn_mrb_table_cursor_init(grn_ctx * ctx)182 grn_mrb_table_cursor_init(grn_ctx *ctx)
183 {
184 grn_mrb_data *data = &(ctx->impl->mrb);
185 mrb_state *mrb = data->state;
186 struct RClass *module = data->module;
187 struct RClass *klass;
188
189 klass = mrb_define_class_under(mrb, module, "TableCursor", mrb->object_class);
190 MRB_SET_INSTANCE_TT(klass, MRB_TT_DATA);
191
192 mrb_define_class_method(mrb, klass, "open_raw",
193 mrb_grn_table_cursor_class_open_raw,
194 MRB_ARGS_ARG(1, 1));
195
196 mrb_define_method(mrb, klass, "initialize",
197 mrb_grn_table_cursor_initialize, MRB_ARGS_REQ(1));
198 mrb_define_method(mrb, klass, "close",
199 mrb_grn_table_cursor_close, MRB_ARGS_NONE());
200 mrb_define_method(mrb, klass, "next",
201 mrb_grn_table_cursor_next, MRB_ARGS_NONE());
202 mrb_define_method(mrb, klass, "count",
203 mrb_grn_table_cursor_count, MRB_ARGS_NONE());
204
205 mrb_define_method(mrb, klass, "key",
206 mrb_grn_table_cursor_get_key, MRB_ARGS_NONE());
207 }
208 #endif
209