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-1301 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
36static struct mrb_data_type mrb_grn_table_cursor_type = {
37 "Groonga::TableCursor",
38 NULL
39};
40
41static mrb_value
42mrb_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
106static mrb_value
107mrb_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
118static mrb_value
119mrb_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
134static mrb_value
135mrb_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
146static mrb_value
147mrb_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
159static mrb_value
160mrb_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
181void
182grn_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