/* * 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; }
/* * 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; }
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; }
/* * 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; }
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; }
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)); }
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; }