Navigation Menu

Skip to content

Commit

Permalink
Add Groonga::RegexpOperator#exec
Browse files Browse the repository at this point in the history
  • Loading branch information
kou committed Apr 14, 2015
1 parent 37f8084 commit f0d97b5
Show file tree
Hide file tree
Showing 5 changed files with 125 additions and 3 deletions.
3 changes: 2 additions & 1 deletion ext/groonga/rb-grn-operator.c
Expand Up @@ -309,6 +309,7 @@ rb_grn_init_operator (VALUE mGrn)
rb_grn_init_greater_equal_operator(mGrn);
rb_grn_init_match_operator(mGrn);
rb_grn_init_prefix_operator(mGrn);
rb_grn_init_regexp_operator(mGrn);

rb_define_const(rb_cGrnOperator, "PUSH",
rb_funcall(rb_cGrnOperator, rb_intern("new"), 2,
Expand Down Expand Up @@ -620,7 +621,7 @@ rb_grn_init_operator (VALUE mGrn)
rb_str_new_cstr("json-put"),
UINT2NUM(GRN_OP_JSON_PUT)));
rb_define_const(rb_cGrnOperator, "REGEXP",
rb_funcall(rb_cGrnOperator, rb_intern("new"), 2,
rb_funcall(rb_cGrnRegexpOperator, rb_intern("new"), 2,
rb_str_new_cstr("regexp"),
UINT2NUM(GRN_OP_REGEXP)));

Expand Down
85 changes: 85 additions & 0 deletions ext/groonga/rb-grn-regexp-operator.c
@@ -0,0 +1,85 @@
/* -*- coding: utf-8; mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2015 Kouhei Sutou <kou@clear-code.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#include "rb-grn.h"

VALUE rb_cGrnRegexpOperator;

/*
* Executes a regular expression match operation.
*
* @example Executes regular expression match operations with the default context
* Groonga::Operator::REGEXP.exec("Hello Rroonga", /Rro+nga/) # => true
* Groonga::Operator::REGEXP.exec("Hello Rroonga", /Gro+nga/) # => false
*
* @example Executes regular expression match operations with the specified context
* context = Groonga::Context.new
* Groonga::Operator::REGEXP.exec("Hello Rroonga", /Rro+nga/,
* :context => context) # => true
* Groonga::Operator::REGEXP.exec("Hello Rroonga", /Gro+nga/,
* :context => context) # => false
*
* @overload exec(text, regexp, options={})
* @param text [String] The text to be matched.
* @param regexp [Regexp] The regular expression.
* @param options [::Hash] The options.
* @option options [Groonga::Context] (Groonga::Context.default)
* The context to executes the operation.
* @return [Boolean] `true` if `text` matches `regexp`, `false`
* otherwise.
*/
static VALUE
rb_grn_regexp_operator_exec (int argc, VALUE *argv, VALUE self)
{
grn_bool matched;
VALUE rb_text;
VALUE rb_regexp;
VALUE rb_options;
VALUE rb_context;
grn_ctx *context;
grn_obj text;
grn_obj regexp;

rb_scan_args(argc, argv, "21", &rb_text, &rb_regexp, &rb_options);

rb_grn_scan_options(rb_options,
"context", &rb_context,
NULL);
context = rb_grn_context_ensure(&rb_context);

GRN_VOID_INIT(&text);
GRN_VOID_INIT(&regexp);
RVAL2GRNBULK(rb_text, context, &text);
RVAL2GRNBULK(rb_regexp, context, &regexp);
matched = grn_operator_exec_regexp(context, &text, &regexp);
GRN_OBJ_FIN(context, &text);
GRN_OBJ_FIN(context, &regexp);

return CBOOL2RVAL(matched);
}

void
rb_grn_init_regexp_operator (VALUE mGrn)
{
rb_cGrnRegexpOperator = rb_define_class_under(mGrn,
"RegexpOperator",
rb_cGrnOperator);

rb_define_method(rb_cGrnRegexpOperator, "exec",
rb_grn_regexp_operator_exec, -1);
}
17 changes: 15 additions & 2 deletions ext/groonga/rb-grn-utils.c
Expand Up @@ -370,6 +370,8 @@ rb_grn_bulk_to_ruby_object (grn_ctx *context, grn_obj *bulk,
grn_obj *
rb_grn_bulk_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *bulk)
{
int object_type;

if (bulk && bulk->header.domain == GRN_DB_TIME)
return RVAL2GRNBULK_WITH_TYPE(object, context, bulk,
bulk->header.domain,
Expand All @@ -380,13 +382,24 @@ rb_grn_bulk_from_ruby_object (VALUE object, grn_ctx *context, grn_obj *bulk)
rb_grn_context_check(context, object);
}

switch (TYPE(object)) {
object_type = TYPE(object);
switch (object_type) {
case T_NIL:
grn_obj_reinit(context, bulk, GRN_DB_VOID, 0);
break;
case T_SYMBOL:
object = rb_funcall(object, rb_intern("to_s"), 0);
case T_REGEXP:
case T_STRING:
switch (object_type) {
case T_SYMBOL:
object = rb_funcall(object, rb_intern("to_s"), 0);
break;
case T_REGEXP:
object = rb_funcall(object, rb_intern("source"), 0);
break;
default:
break;
}
grn_obj_reinit(context, bulk, GRN_DB_TEXT, 0);
rb_grn_context_text_set(context, bulk, object);
break;
Expand Down
2 changes: 2 additions & 0 deletions ext/groonga/rb-grn.h
Expand Up @@ -294,6 +294,7 @@ RB_GRN_VAR VALUE rb_cGrnLessEqualOperator;
RB_GRN_VAR VALUE rb_cGrnGreaterEqualOperator;
RB_GRN_VAR VALUE rb_cGrnMatchOperator;
RB_GRN_VAR VALUE rb_cGrnPrefixOperator;
RB_GRN_VAR VALUE rb_cGrnRegexpOperator;
RB_GRN_VAR VALUE rb_cGrnExpression;
RB_GRN_VAR VALUE rb_cGrnRecordExpressionBuilder;
RB_GRN_VAR VALUE rb_cGrnColumnExpressionBuilder;
Expand Down Expand Up @@ -341,6 +342,7 @@ void rb_grn_init_less_equal_operator (VALUE mGrn);
void rb_grn_init_greater_equal_operator (VALUE mGrn);
void rb_grn_init_match_operator (VALUE mGrn);
void rb_grn_init_prefix_operator (VALUE mGrn);
void rb_grn_init_regexp_operator (VALUE mGrn);
void rb_grn_init_expression (VALUE mGrn);
void rb_grn_init_expression_builder (VALUE mGrn);
void rb_grn_init_logger (VALUE mGrn);
Expand Down
21 changes: 21 additions & 0 deletions test/test-operator.rb
Expand Up @@ -184,4 +184,25 @@ class OperatorTest < Test::Unit::TestCase
end
end
end

sub_test_case "regexp" do
sub_test_case "#exec" do
test "match" do
assert_true(Groonga::Operator::REGEXP.exec("Hello Rroonga",
/Rro+nga/))
end

test "not match" do
assert_false(Groonga::Operator::REGEXP.exec("Hello Rroonga",
/Gro+nga/))
end

test ":context" do
context = Groonga::Context.new
assert_true(Groonga::Operator::REGEXP.exec("Hello Rroonga",
/Rro+nga/,
:context => context))
end
end
end
end

0 comments on commit f0d97b5

Please sign in to comment.