/*
* call-seq:
* select(string, option=>value, ...)
* select(string, recs, option=>value, ...)
* select(string, recs, op, option=>value, ...)
*
* インデックスの検索。
*
* 有効な option:
* :mode [Integer] :: 次のいずれか。Senna::SEL_EXACT, Senna::SEL_PARTIAL, Senna::SEL_UNSPLIT, Senna::SEL_NEAR, Senna::SEL_SIMILAR, Senna::SEL_PREFIX, Senna::SEL_SUFFIX
* :similarity_threshold [Integer] :: Senna API DOC 参照
* :max_interval [Integer] :: Senna API DOC 参照
* :weight_vector [Array of Integer] :: Senna API DOC 参照
* :vector_size [Integer] :: Senna API DOC 参照
*
* === Argument
* string [String] :: 検索する文字列
* recs [Senna::Records] :: 結果が反映されるレコード群。未指定時は空の Senna::Records が作成される。
* op [Integer] :: 次のいずれか。Senna::SEL_OR(default), Senna::SEL_AND, Senna::SEL_BUT, Senna::SEL_ADJUST
*
* === Return
* Senna::Records :: recs と同じ。
*/
static VALUE index_select(int argc, VALUE *argv, VALUE obj)
{
VALUE string;
VALUE arg1, arg2, arg3;
VALUE recs = Qnil;
VALUE op = Qnil;
VALUE optarg = Qnil;
struct index_data *data;
sen_records *_recs;
sen_sel_operator _op;
sen_select_optarg _optarg, *_optarg_p;
sen_rc rc;
int n;
n = rb_scan_args(argc, argv, "13", &string, &arg1, &arg2, &arg3);
Check_Type(string, T_STRING);
switch (n) {
case 1:
break;
case 2:
if (TYPE(arg1) == T_HASH)
optarg = arg1;
else
recs = arg1;
break;
case 3:
recs = arg1;
if (TYPE(arg2) == T_HASH)
optarg = arg2;
else
op = arg2;
break;
case 4:
recs = arg1;
op = arg2;
optarg = arg3;
break;
}
if (NIL_P(recs)) {
_recs = sen_records_open(sen_rec_document, sen_rec_none, 0);
recs = Data_Wrap_Struct(cSennaRecords, 0, sen_records_close, _recs);
} else {
if (!rb_obj_is_kind_of(recs, cSennaRecords))
rb_raise(rb_eTypeError, "wrong argument type %s (expected Senna::Records)", rb_obj_classname(recs));
Data_Get_Struct(recs, sen_records, _recs);
}
_op = NIL_P(op) ? sen_sel_or : NUM2INT(op);
if (NIL_P(optarg)) {
_optarg_p = NULL;
} else {
VALUE mode, st, mi, wv, vs;
sen_sel_mode _mode;
int _st, _mi, *_wv, _vs;
int i;
Check_Type(optarg, T_HASH);
mode = rb_hash_aref(optarg, ID2SYM(rb_intern("mode")));
_mode = NIL_P(mode) ? sen_sel_exact : NUM2INT(mode);
st = rb_hash_aref(optarg, ID2SYM(rb_intern("similarity_threshold")));
_st = NIL_P(st) ? 0 : NUM2INT(st);
mi = rb_hash_aref(optarg, ID2SYM(rb_intern("max_interval")));
_mi = NIL_P(mi) ? 0 : NUM2INT(mi);
wv = rb_hash_aref(optarg, ID2SYM(rb_intern("weight_vector")));
if (!NIL_P(wv)) {
Check_Type(wv, T_ARRAY);
_wv = xmalloc(RARRAY_LEN(wv) * sizeof(int));
for (i = 0; i < RARRAY_LEN(wv); i += 1) {
_wv[i] = NUM2INT(RARRAY_PTR(wv)[i]);
}
_vs = RARRAY_LEN(wv);
} else {
_wv = NULL;
vs = rb_hash_aref(optarg, ID2SYM(rb_intern("vector_size")));
_vs = NIL_P(vs) ? 0 : NUM2INT(vs);
}
_optarg.mode = _mode;
_optarg.similarity_threshold = _st;
_optarg.max_interval = _mi;
_optarg.weight_vector = _wv;
_optarg.vector_size = _vs;
_optarg.func = NULL;
_optarg_p = &_optarg;
}
Data_Get_Struct(obj, struct index_data, data);
if (data->closed)
rb_raise(rb_eRuntimeError, "already closed");
rc = sen_index_select(data->indexp, RSTRING_PTR(string), RSTRING_LEN(string), _recs, _op, _optarg_p);
if (rc != sen_success)
senna_error(rc, "sen_index_select failed");
return recs;
}