/*
 * call-seq:
 *   _expression_.inspect -> String
 *
 * _expression_の中身を人に見やすい文字列で返す。
 */
static VALUE
rb_grn_expression_inspect (VALUE self)
{
    grn_ctx *context = NULL;
    grn_obj inspected;
    grn_obj *expression;
    VALUE rb_inspected;

    rb_grn_expression_deconstruct(SELF(self), &expression, &context,
                                  NULL, NULL,
                                  NULL, NULL, NULL);

    GRN_TEXT_INIT(&inspected, 0);
    GRN_TEXT_PUTS(context, &inspected, "#<Groonga::Expression ");
#ifdef WIN32
    GRN_TEXT_PUTS(context, &inspected, "(not supported on Windows)");
#else
    grn_expr_inspect(context, &inspected, expression);
#endif
    GRN_TEXT_PUTS(context, &inspected, ">");
    rb_inspected = rb_grn_context_rb_string_new(context,
						GRN_TEXT_VALUE(&inspected),
						GRN_TEXT_LEN(&inspected));
    GRN_OBJ_FIN(context, &inspected);

    return rb_inspected;
}
/*
 * Normalizes the @string@.
 *
 * @example
 *   # Normalizes "ABC" with the default normalizer
 *   Groonga::Normalizer.normalize("AbC") # => "abc"
 *
 * @overload normalize(string)
 *   @return [String] The normalized string
 *   @param [String] string The original string
 */
static VALUE
rb_grn_normalizer_s_normalize (VALUE klass, VALUE rb_string)
{
    VALUE rb_context = Qnil;
    VALUE rb_encoded_string;
    VALUE rb_normalized_string;
    grn_ctx *context = NULL;
    grn_obj *grn_string;
    grn_obj *normalizer = GRN_NORMALIZER_AUTO;
    /* TODO: make customizable */
    int flags = GRN_STRING_REMOVE_BLANK;
    const char *normalized_string;
    unsigned int normalized_string_length;

    context = rb_grn_context_ensure(&rb_context);
    rb_encoded_string = rb_grn_context_rb_string_encode(context, rb_string);
    grn_string = grn_string_open(context,
                                 RSTRING_PTR(rb_encoded_string),
                                 RSTRING_LEN(rb_encoded_string),
                                 normalizer,
                                 flags);
    rb_grn_context_check(context, rb_string);
    grn_string_get_normalized(context, grn_string,
                              &normalized_string, &normalized_string_length,
                              NULL);
    rb_normalized_string =
        rb_grn_context_rb_string_new(context,
                                     normalized_string,
                                     normalized_string_length);
    grn_obj_close(context, grn_string);

    return rb_normalized_string;
}
Exemple #3
0
/*
 * Gets a configuration value for key.
 *
 * @overload config[](key)
 *   @param [String] key The key.
 *   @return [String, nil] The value associated with `key`.
 *
 * @since 5.0.9
 */
static VALUE
rb_grn_config_get (VALUE self, VALUE rb_key)
{
    VALUE rb_context;
    VALUE rb_value;
    grn_ctx *context;
    const char *key;
    int key_size;
    const char *value;
    uint32_t value_size;

    rb_context = rb_iv_get(self, "@context");
    context = rb_grn_context_ensure(&rb_context);

    rb_key = rb_grn_convert_to_string(rb_key);
    key = RSTRING_PTR(rb_key);
    key_size = RSTRING_LEN(rb_key);

    {
        grn_rc rc;
        rc = grn_config_get(context,
                            key, key_size,
                            &value, &value_size);
        rb_grn_context_check(context, self);
        rb_grn_rc_check(rc, self);
    }

    if (value_size == 0) {
        rb_value = Qnil;
    } else {
        rb_value = rb_grn_context_rb_string_new(context, value, value_size);
    }

    return rb_value;
}
/*
 * call-seq:
 *   patricia_trie.scan(string) -> Array
 *   patricia_trie.scan(string) {|record, word, start, length| ... }
 *
 * _string_を走査し、_patricia_trie_内に格納されているキーに
 * マッチした部分文字列の情報をブロックに渡す。複数のキーが
 * マッチする場合は最長一致するキーを優先する。
 *
 * [_record_]
 *   マッチしたキーのGroonga::Record。
 *
 * [_word_]
 *   マッチした部分文字列。
 *
 * [_start_]
 *   _string_内での_word_の出現位置。(バイト単位)
 *
 * [_length_]
 *   _word_の長さ。(バイト単位)
 *
 * ブロックを指定しない場合は、マッチした部分文字列の情報を
 * まとめて配列として返す。
 *
 *   words = Groonga::PatriciaTrie.create(:key_type => "ShortText",
 *                                        :key_normalize => true)
 *   words.add("リンク")
 *   adventure_of_link = words.add('リンクの冒険')
 *   words.add('冒険')
 *   gaxtu = words.add('ガッ')
 *   muteki = words.add('MUTEKI')
 *
 *   text = 'muTEki リンクの冒険 ミリバール ガッ'
 *   words.scan(text).each do |record, word, start, length|
 *     p [record.key, word, start, length]
 *       # -> ["MUTEKI", "muTEki", 0, 6]
 *       # -> ["リンクの冒険", "リンクの冒険", 7, 18]
 *       # -> ["ガッ", "ガッ", 42, 6]
 *   end
 *
 *   words.scan(text)
 *     # -> [[muteki, "muTEki", 0, 6],
 *     #     [adventure_of_link, "リンクの冒険", 7, 18],
 *     #     [gaxtu, "ガッ", 42, 6]]
 */
static VALUE
rb_grn_patricia_trie_scan (VALUE self, VALUE rb_string)
{
    grn_ctx *context;
    grn_obj *table;
    VALUE rb_result = Qnil;
    grn_pat_scan_hit hits[1024];
    const char *string;
    long string_length;
    grn_bool block_given;

    string = StringValuePtr(rb_string);
    string_length = RSTRING_LEN(rb_string);

    rb_grn_table_key_support_deconstruct(SELF(self), &table, &context,
					 NULL, NULL, NULL,
					 NULL, NULL, NULL,
					 NULL);

    block_given = rb_block_given_p();
    if (!block_given)
	rb_result = rb_ary_new();

    while (string_length > 0) {
	const char *rest;
	int i, n_hits;
	unsigned int previous_offset = 0;

	n_hits = grn_pat_scan(context, (grn_pat *)table,
			      string, string_length,
			      hits, sizeof(hits) / sizeof(*hits),
			      &rest);
	for (i = 0; i < n_hits; i++) {
	    VALUE record, term, matched_info;

	    if (hits[i].offset < previous_offset)
		continue;

	    record = rb_grn_record_new(self, hits[i].id, Qnil);
	    term = rb_grn_context_rb_string_new(context,
						string + hits[i].offset,
						hits[i].length);
	    matched_info = rb_ary_new3(4,
				       record,
				       term,
				       UINT2NUM(hits[i].offset),
				       UINT2NUM(hits[i].length));
	    if (block_given) {
		rb_yield(matched_info);
	    } else {
		rb_ary_push(rb_result, matched_info);
	    }
	    previous_offset = hits[i].offset;
	}
	string_length -= rest - string;
	string = rest;
    }

    return rb_result;
}
Exemple #5
0
static VALUE
rb_grn_bulk_to_ruby_object_by_range_id (grn_ctx *context, grn_obj *bulk,
					grn_id range_id,
					VALUE related_object, VALUE *rb_value)
{
    grn_bool success = GRN_TRUE;

    switch (range_id) {
      case GRN_DB_VOID:
	*rb_value = rb_str_new(GRN_TEXT_VALUE(bulk), GRN_TEXT_LEN(bulk));
	break;
      case GRN_DB_BOOL:
	*rb_value = GRN_BOOL_VALUE(bulk) ? Qtrue : Qfalse;
	break;
      case GRN_DB_INT32:
	*rb_value = INT2NUM(GRN_INT32_VALUE(bulk));
	break;
      case GRN_DB_UINT32:
	*rb_value = UINT2NUM(GRN_UINT32_VALUE(bulk));
	break;
      case GRN_DB_INT64:
	*rb_value = LL2NUM(GRN_INT64_VALUE(bulk));
	break;
      case GRN_DB_UINT64:
	*rb_value = ULL2NUM(GRN_UINT64_VALUE(bulk));
	break;
      case GRN_DB_FLOAT:
	*rb_value = rb_float_new(GRN_FLOAT_VALUE(bulk));
	break;
      case GRN_DB_TIME:
	{
	    int64_t time_value, sec, usec;

	    time_value = GRN_TIME_VALUE(bulk);
	    GRN_TIME_UNPACK(time_value, sec, usec);
	    *rb_value = rb_funcall(rb_cTime, rb_intern("at"), 2,
				   LL2NUM(sec), LL2NUM(usec));
	}
	break;
      case GRN_DB_SHORT_TEXT:
      case GRN_DB_TEXT:
      case GRN_DB_LONG_TEXT:
	*rb_value = rb_grn_context_rb_string_new(context,
						 GRN_TEXT_VALUE(bulk),
						 GRN_TEXT_LEN(bulk));
	break;
      default:
	success = GRN_FALSE;
	break;
    }

    return success;
}
Exemple #6
0
/*
 * call-seq:
 *   snippet.execute(string) -> スニペットの配列
 *
 * _string_を走査し、スニペットを作成する。
 */
static VALUE
rb_grn_snippet_execute (VALUE self, VALUE rb_string)
{
    RbGrnSnippet *rb_grn_snippet;
    grn_rc rc;
    grn_ctx *context;
    grn_snip *snippet;
    char *string;
    unsigned int string_length;
    unsigned int i, n_results, max_tagged_length;
    VALUE rb_results;
    char *result;

    if (TYPE(rb_string) != T_STRING) {
	rb_raise(rb_eGrnInvalidArgument,
		 "snippet text must be String: <%s>",
		 rb_grn_inspect(rb_string));
    }

    rb_grn_snippet = SELF(self);
    context = rb_grn_snippet->context;
    snippet = rb_grn_snippet->snippet;

#ifdef HAVE_RUBY_ENCODING_H
    rb_string = rb_grn_context_rb_string_encode(context, rb_string);
#endif
    string = StringValuePtr(rb_string);
    string_length = RSTRING_LEN(rb_string);

    rc = grn_snip_exec(context, snippet, string, string_length,
                       &n_results, &max_tagged_length);
    rb_grn_rc_check(rc, self);

    rb_results = rb_ary_new2(n_results);
    result = ALLOCA_N(char, max_tagged_length);
    for (i = 0; i < n_results; i++) {
        VALUE rb_result;
        unsigned result_length;

        rc = grn_snip_get_result(context, snippet, i, result, &result_length);
        rb_grn_rc_check(rc, self);
        rb_result = rb_grn_context_rb_string_new(context, result, result_length);
        rb_ary_push(rb_results, rb_result);
    }

    return rb_results;
}
Exemple #7
0
static VALUE
rb_grn_expression_inspect (VALUE self)
{
    grn_ctx *context = NULL;
    grn_obj *expression;
    grn_obj inspected;
    VALUE rb_inspected;

    rb_grn_expression_deconstruct(SELF(self), &expression, &context,
                                  NULL, NULL,
                                  NULL, NULL, NULL);

    rb_inspected = rb_str_new_cstr("");
    rb_grn_object_inspect_header(self, rb_inspected);

    GRN_TEXT_INIT(&inspected, 0);
    grn_inspect(context, &inspected, expression);
    grn_bulk_truncate(context, &inspected, GRN_TEXT_LEN(&inspected) - 2);
    {
        size_t prefix_length;
        const char *content;
        size_t content_length;

        prefix_length = strlen("#<expr");
        content = GRN_TEXT_VALUE(&inspected) + prefix_length;
        content_length = GRN_TEXT_LEN(&inspected) - prefix_length;
        rb_str_concat(rb_inspected,
                      rb_grn_context_rb_string_new(context,
                                                   content,
                                                   content_length));
    }

    GRN_OBJ_FIN(context, &inspected);

    rb_grn_object_inspect_footer(self, rb_inspected);

    return rb_inspected;
}
Exemple #8
0
VALUE
rb_grn_bulk_to_ruby_object (grn_ctx *context, grn_obj *bulk,
                            grn_obj *range, VALUE related_object)
{
    grn_id range_id;
    VALUE rb_value = Qnil;

    if (GRN_BULK_EMPTYP(bulk))
        return Qnil;

    range_id = bulk->header.domain;
    if (rb_grn_bulk_to_ruby_object_by_range_id(context, bulk, range_id,
                                               related_object, &rb_value))
        return rb_value;

    if (rb_grn_bulk_to_ruby_object_by_range_type(context, bulk,
                                                 range, range_id,
                                                 related_object, &rb_value))
        return rb_value;

    return rb_grn_context_rb_string_new(context,
                                        GRN_BULK_HEAD(bulk),
                                        GRN_BULK_VSIZE(bulk));
}
Exemple #9
0
static VALUE
rb_grn_bulk_to_ruby_object_by_range_type (grn_ctx *context, grn_obj *bulk,
                                          grn_obj *range, grn_id range_id,
                                          VALUE related_object, VALUE *rb_value)
{
    grn_bool success = GRN_TRUE;

    if (!range && range_id != GRN_ID_NIL) {
        range = grn_ctx_at(context, range_id);
    }

    if (!range)
        return GRN_FALSE;

    switch (range->header.type) {
    case GRN_TABLE_HASH_KEY:
    case GRN_TABLE_PAT_KEY:
    case GRN_TABLE_DAT_KEY:
    case GRN_TABLE_NO_KEY: {
        grn_id id;

        id = *((grn_id *)GRN_BULK_HEAD(bulk));
        if (id == GRN_ID_NIL) {
            *rb_value = Qnil;
        } else {
            VALUE rb_range;

            rb_range = GRNOBJECT2RVAL(Qnil, context, range, GRN_FALSE);
            *rb_value = rb_grn_record_new(rb_range, id, Qnil);
        }
        break;
    }
    case GRN_TYPE:
        if (range->header.flags & GRN_OBJ_KEY_VAR_SIZE) {
            *rb_value = rb_grn_context_rb_string_new(context,
                                                     GRN_BULK_HEAD(bulk),
                                                     GRN_BULK_VSIZE(bulk));
        } else {
            switch (range->header.flags & GRN_OBJ_KEY_MASK) {
            case GRN_OBJ_KEY_UINT:
                *rb_value = INT2NUM(GRN_UINT32_VALUE(bulk));
                break;
            case GRN_OBJ_KEY_INT:
                *rb_value = INT2NUM(GRN_INT32_VALUE(bulk));
                break;
            case GRN_OBJ_KEY_FLOAT:
                *rb_value = rb_float_new(GRN_FLOAT_VALUE(bulk));
                break;
            default:
                success = GRN_FALSE;
            }
            break;
        }
        break;
    default:
        success = GRN_FALSE;
        break;
    }

    return success;
}