/* * 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; }
/* * call-seq: * patricia_trie.prefix_search(prefix) -> Groonga::Hash * * キーが_prefix_に前方一致するレコードのIDがキーに入っている * Groonga::Hashを返す。マッチするレコードがない場合は空の * Groonga::Hashが返る。 * */ static VALUE rb_grn_patricia_trie_prefix_search (VALUE self, VALUE rb_prefix) { grn_ctx *context; grn_obj *table, *key, *domain, *result; grn_id domain_id; VALUE rb_result; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); result = grn_table_create(context, NULL, 0, NULL, GRN_OBJ_TABLE_HASH_KEY, table, 0); rb_grn_context_check(context, self); rb_result = GRNOBJECT2RVAL(Qnil, context, result, GRN_TRUE); GRN_BULK_REWIND(key); RVAL2GRNKEY(rb_prefix, context, key, domain_id, domain, self); grn_pat_prefix_search(context, (grn_pat *)table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key), (grn_hash *)result); rb_grn_context_check(context, self); return rb_result; }
/* * _table_ の _key_ に対応するカラム _column_name_ の値を設定する。 * _key_ に対応するレコードがない場合は新しく作成される。 * * 0.9.0から値ではなくカラムの値を設定するようになった。 * * @overload []=(key, values) * @param [::Hash] values * keyに対応させるカラムの値。{ :column_name => value, ... }の形で設定する。 */ static VALUE rb_grn_table_key_support_array_set (VALUE self, VALUE rb_key, VALUE rb_values) { grn_id id; SetValueData data; grn_ctx *context; grn_obj *table; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); id = rb_grn_table_key_support_add_raw(self, rb_key, NULL); if (id == GRN_ID_NIL) { rb_raise(rb_eGrnError, "failed to add record: %s", rb_grn_inspect(rb_ary_new3(3, self, rb_key, rb_values))); } data.self = self; data.id = id; data.table = table; data.rb_grn_object.context = context; rb_iterate(rb_each, rb_values, set_value, (VALUE)&data); return Qnil; }
static void rb_grn_double_array_trie_deconstruct (RbGrnDoubleArrayTrie *rb_grn_double_array_trie, grn_obj **double_array_trie, grn_ctx **context, grn_obj **key, grn_obj **new_key, grn_id *domain_id, grn_obj **domain, grn_obj **value, grn_id *range_id, grn_obj **range, VALUE *columns) { RbGrnTableKeySupport *rb_grn_table_key_support; rb_grn_table_key_support = RB_GRN_TABLE_KEY_SUPPORT(rb_grn_double_array_trie); rb_grn_table_key_support_deconstruct(rb_grn_table_key_support, double_array_trie, context, key, domain_id, domain, value, range_id, range, columns); if (new_key) *new_key = rb_grn_double_array_trie->new_key; }
/* * テーブルの _id_ に対応する主キーを返す。 * * @overload key(id) * @return [主キー] */ static VALUE rb_grn_table_key_support_get_key (VALUE self, VALUE rb_id) { grn_ctx *context; grn_obj *table, *key; grn_id id; int key_size; VALUE rb_key; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, NULL, NULL, NULL, NULL, NULL, NULL); id = NUM2UINT(rb_id); GRN_BULK_REWIND(key); key_size = grn_table_get_key(context, table, id, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key)); if (key_size == 0) return Qnil; if (GRN_BULK_VSIZE(key) < key_size) { grn_bulk_reserve(context, key, key_size); grn_table_get_key(context, table, id, GRN_BULK_HEAD(key), key_size); } rb_key = GRNKEY2RVAL(context, GRN_BULK_HEAD(key), key_size, table, self); return rb_key; }
/* * テーブルでキーを使えるなら +true+ 、使えないなら +false+ を返 * す。キーを使えないテーブルは {Groonga::Array} だけ。 * * @overload support_key? */ static VALUE rb_grn_table_key_support_support_key_p (VALUE self) { grn_obj *table; rb_grn_table_key_support_deconstruct(SELF(self), &table, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); return table->header.domain == GRN_ID_NIL ? Qfalse : Qtrue; }
/* * キーを正規化する場合は +true+ 、正規化しない場合は +false+ を返 * す。 * * @overload normalize_key? */ static VALUE rb_grn_table_key_normalize_key_p (VALUE self) { grn_obj *table; rb_grn_table_key_support_deconstruct(SELF(self), &table, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); return CBOOL2RVAL(table->header.flags & GRN_OBJ_KEY_NORMALIZE); }
/* * call-seq: * table.register_key_with_sis? -> true/false * * キーを登録するときに文字列の全suffixも一緒に登録する場合 * は+true+、登録しない場合は+false+を返す。 */ static VALUE rb_grn_patricia_trie_register_key_with_sis_p (VALUE self) { grn_obj *table; rb_grn_table_key_support_deconstruct(SELF(self), &table, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); return CBOOL2RVAL(table->header.flags & GRN_OBJ_KEY_WITH_SIS); }
/* * call-seq: * patricia_trie.search(key, options=nil) -> Groonga::Hash * * _key_にマッチするレコードのIDがキーに入っている * Groonga::Hashを返す。マッチするレコードがない場合は空の * Groonga::Hashが返る。 * * _options_で+:result+を指定することにより、そのテーブルにマッ * チしたレコードIDがキーのレコードを追加することができる。 * +:result+にテーブルを指定した場合は、そのテーブルが返る。 * * _options_に指定可能な値は以下の通り。 * * [+:result+] * 結果を格納するテーブル。 * * [+:operator+] * マッチしたレコードをどのように扱うか。指定可能な値は以 * 下の通り。省略した場合はGroonga::Operator::OR。 * * [Groonga::Operator::OR] * マッチしたレコードを追加。すでにレコードが追加され * ている場合は何もしない。 * [Groonga::Operator::AND] * マッチしたレコードのスコアを増加。マッチしなかった * レコードを削除。 * [Groonga::Operator::BUT] * マッチしたレコードを削除。 * [Groonga::Operator::ADJUST] * マッチしたレコードのスコアを増加。 * * [+:type+] * ????? * * 複数のキーで検索し、結果を1つのテーブルに集める。 * result = nil * keys = ["morita", "gunyara-kun", "yu"] * keys.each do |key| * result = users.search(key, :result => result) * end * result.each do |record| * user = record.key * p user.key # -> "morita"または"gunyara-kun"または"yu" * end */ static VALUE rb_grn_patricia_trie_search (int argc, VALUE *argv, VALUE self) { grn_rc rc; grn_ctx *context; grn_obj *table; grn_id domain_id; grn_obj *key, *domain, *result; grn_operator operator; grn_search_optarg search_options; grn_bool search_options_is_set = GRN_FALSE; VALUE rb_key, options, rb_result, rb_operator, rb_type; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); rb_scan_args(argc, argv, "11", &rb_key, &options); RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self); rb_grn_scan_options(options, "result", &rb_result, "operator", &rb_operator, "type", &rb_type, NULL); if (NIL_P(rb_result)) { result = grn_table_create(context, NULL, 0, NULL, GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC, table, 0); rb_grn_context_check(context, self); rb_result = GRNOBJECT2RVAL(Qnil, context, result, GRN_TRUE); } else { result = RVAL2GRNOBJECT(rb_result, &context); } operator = RVAL2GRNOPERATOR(rb_operator); rc = grn_obj_search(context, table, key, result, operator, search_options_is_set ? &search_options : NULL); rb_grn_rc_check(rc, self); return rb_result; }
/* * Returns the normalizer that is used by {Groonga::IndexColumn}. * * @overload normalizer * @return [nil, Groonga::Procedure] */ static VALUE rb_grn_table_key_support_get_normalizer (VALUE self) { grn_ctx *context = NULL; grn_obj *table; grn_obj *normalizer = NULL; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); normalizer = grn_obj_get_info(context, table, GRN_INFO_NORMALIZER, NULL); rb_grn_context_check(context, self); return GRNOBJECT2RVAL(Qnil, context, normalizer, GRN_FALSE); }
/* * テーブルに主キーが _key_ のレコードがあるならtrueを返す。 * * @overload has_key?(key) */ static VALUE rb_grn_table_key_support_has_key (VALUE self, VALUE rb_key) { grn_ctx *context; grn_obj *table, *key, *domain; grn_id id, domain_id; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); GRN_BULK_REWIND(key); RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self); id = grn_table_get(context, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key)); return id == GRN_ID_NIL ? Qfalse : Qtrue; }
/* * {Groonga::IndexColumn} で使用するトークナイザを返す。 * * @overload default_tokenizer * @return [nilまたはGroonga::Procedure] */ static VALUE rb_grn_table_key_support_get_default_tokenizer (VALUE self) { grn_ctx *context = NULL; grn_obj *table; grn_obj *tokenizer = NULL; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); tokenizer = grn_obj_get_info(context, table, GRN_INFO_DEFAULT_TOKENIZER, NULL); rb_grn_context_check(context, self); return GRNOBJECT2RVAL(Qnil, context, tokenizer, GRN_FALSE); }
/* * Specifies the normalizer used by {Groonga::IndexColumn}. * * @example * # Uses NFKC normalizer. * table.normalizer = "NormalizerNFKC51" * # Specifies normalizer object. * table.normalizer = Groonga::Context["NormalizerNFKC51"] * # Uses auto normalizer that is a normalizer for backward compatibility. * table.normalizer = "TNormalizerAuto" * * @overload normalizer=(name) * @param [String] name Set a nomalizer named @name@. * * @overload normalizer=(normalizer) * @param [Groonga::Procedure] normalizer Set the normalizer object. * * @overload normalizer=(normalizer) * @param [nil] normalizer Unset normalizer. */ static VALUE rb_grn_table_key_support_set_normalizer (VALUE self, VALUE rb_normalizer) { grn_ctx *context; grn_obj *table; grn_obj *normalizer; grn_rc rc; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); normalizer = RVAL2GRNOBJECT(rb_normalizer, &context); rc = grn_obj_set_info(context, table, GRN_INFO_NORMALIZER, normalizer); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return Qnil; }
/* * Tokenize a string using the table as lexicon. * * @overload tokenize(string, options={}) * @param [String] string The string to be tokenized. * @param [::Hash] options * @option options [Bool] :add (true) Adds a new token to the table if true. * Returned tokens include the new token. Otherwise, a new token is * just ignored. * @return [::Array<Groonga::Record>] Tokenized tokens. */ static VALUE rb_grn_table_key_support_tokenize (int argc, VALUE *argv, VALUE self) { VALUE rb_string, rb_add_p; VALUE rb_options; VALUE rb_tokens = Qnil; grn_ctx *context; grn_obj *table; char *string; int string_size; grn_bool add_p; grn_obj tokens; rb_scan_args(argc, argv, "11", &rb_string, &rb_options); rb_grn_scan_options(rb_options, "add", &rb_add_p, NULL); if (NIL_P(rb_add_p)) { rb_add_p = Qtrue; } rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); string = StringValueCStr(rb_string); string_size = RSTRING_LEN(rb_string); add_p = RVAL2CBOOL(rb_add_p); GRN_RECORD_INIT(&tokens, GRN_OBJ_VECTOR, grn_obj_id(context, table)); grn_table_tokenize(context, table, string, string_size, &tokens, add_p); if (context->rc == GRN_SUCCESS) { rb_tokens = GRNUVECTOR2RVAL(context, &tokens, table, self); } grn_obj_unlink(context, &tokens); rb_grn_context_check(context, self); return rb_tokens; }
/* * Returns the token filters that are used by {Groonga::IndexColumn}. * * @overload token_filters * @return [::Array<Groonga::Procedure>] */ static VALUE rb_grn_table_key_support_get_token_filters (VALUE self) { grn_ctx *context = NULL; grn_obj *table; grn_obj token_filters; VALUE rb_token_filters; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); GRN_PTR_INIT(&token_filters, GRN_VECTOR, GRN_ID_NIL); grn_obj_get_info(context, table, GRN_INFO_TOKEN_FILTERS, &token_filters); rb_token_filters = GRNPVECTOR2RVAL(context, &token_filters); rb_grn_context_check(context, self); return rb_token_filters; }
/* * {Groonga::IndexColumn} で使用するトークナイザを設定する。 * * @example * # 2-gramを使用。 * table.default_tokenizer = "TokenBigram" * # オブジェクトで指定 * table.default_tokenizer = Groonga::Context.default["TokenBigram"] * # オブジェクトIDで指定 * table.default_tokenizer = Groonga::Type::BIGRAM * # N-gram用のトークナイザを使うときはGroonga::IndexColumn * # には自動的に:with_section => trueが指定される。 * index = table.define_index_column("blog_content", "Blogs", * :source => "content") * p index # -> #<Groonga::IndexColumn ... flags: <WITH_POSITION|...>> * * # MeCabを使用 * table.default_tokenizer = "TokenMecab" * * @overload default_tokenizer=(tokenizer) */ static VALUE rb_grn_table_key_support_set_default_tokenizer (VALUE self, VALUE rb_tokenizer) { grn_ctx *context; grn_obj *table; grn_obj *tokenizer; grn_rc rc; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); tokenizer = RVAL2GRNOBJECT(rb_tokenizer, &context); rc = grn_obj_set_info(context, table, GRN_INFO_DEFAULT_TOKENIZER, tokenizer); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return Qnil; }
static grn_id rb_grn_table_key_support_add_raw (VALUE self, VALUE rb_key, int *added) { grn_ctx *context; grn_obj *table; grn_id id, domain_id; grn_obj *key, *domain; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); GRN_BULK_REWIND(key); RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self); id = grn_table_add(context, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key), added); rb_grn_context_check(context, self); return id; }
/* * _key_ にマッチするレコードのIDがキーに入っている * {Groonga::Hash} を返す。マッチするレコードがない場合は空の * {Groonga::Hash} が返る。 * * _options_ で +:result+ を指定することにより、そのテーブルにマッ * チしたレコードIDがキーのレコードを追加することができる。 * +:result+ にテーブルを指定した場合は、そのテーブルが返る。 * * @example 複数のキーで検索し、結果を1つのテーブルに集める。 * result = nil * keys = ["morita", "gunyara-kun", "yu"] * keys.each do |key| * result = users.search(key, :result => result) * end * result.each do |record| * user = record.key * p user.key # -> "morita"または"gunyara-kun"または"yu" * end * * @overload search(key, options=nil) * @param [::Hash] options The name and value * pairs. Omitted names are initialized as the default value * @option options :result * 結果を格納するテーブル。 * @return [Groonga::Hash] */ static VALUE rb_grn_hash_search (int argc, VALUE *argv, VALUE self) { grn_rc rc; grn_ctx *context; grn_obj *table; grn_id domain_id; grn_obj *key, *domain, *result; VALUE rb_key, options, rb_result; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); rb_scan_args(argc, argv, "11", &rb_key, &options); RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self); rb_grn_scan_options(options, "result", &rb_result, NULL); if (NIL_P(rb_result)) { result = grn_table_create(context, NULL, 0, NULL, GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC, table, 0); rb_grn_context_check(context, self); rb_result = GRNOBJECT2RVAL(Qnil, context, result, GRN_TRUE); } else { result = RVAL2GRNOBJECT(rb_result, &context); } rc = grn_obj_search(context, table, key, result, GRN_OP_OR, NULL); rb_grn_rc_check(rc, self); return rb_result; }
static VALUE rb_grn_table_key_support_get_value_by_key (VALUE self, VALUE rb_key) { grn_ctx *context; grn_obj *table, *value, *range; grn_id id; id = rb_grn_table_key_support_get(self, rb_key); if (id == GRN_ID_NIL) return Qnil; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, &value, NULL, &range, NULL); GRN_BULK_REWIND(value); grn_obj_get_value(context, table, id, value); rb_grn_context_check(context, self); return GRNBULK2RVAL(context, value, range, self); }
static VALUE rb_grn_table_key_support_delete_by_key (VALUE self, VALUE rb_key) { grn_ctx *context; grn_obj *table; grn_id domain_id; grn_obj *key, *domain; grn_rc rc; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, &key, &domain_id, &domain, NULL, NULL, NULL, NULL); GRN_BULK_REWIND(key); RVAL2GRNKEY(rb_key, context, key, domain_id, domain, self); rc = grn_table_delete(context, table, GRN_BULK_HEAD(key), GRN_BULK_VSIZE(key)); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return Qnil; }
static VALUE rb_grn_table_key_support_set_value_by_key (VALUE self, VALUE rb_key, VALUE rb_value) { grn_ctx *context; grn_obj *table; grn_id id; grn_obj *value; grn_rc rc; if (NIL_P(rb_key)) { rb_raise(rb_eArgError, "key should not be nil: <%s>", rb_grn_inspect(self)); } rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, &value, NULL, NULL, NULL); id = rb_grn_table_key_support_add_raw(self, rb_key, NULL); if (GRN_ID_NIL == id) { rb_raise(rb_eGrnError, "failed to add new record with key: <%s>: <%s>", rb_grn_inspect(rb_key), rb_grn_inspect(self)); } GRN_BULK_REWIND(value); RVAL2GRNBULK(rb_value, context, value); rc = grn_obj_set_value(context, table, id, value, GRN_OBJ_SET); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return rb_value; }
/* * Sets token filters that used in {Groonga::IndexColumn}. * * @example * # Use "TokenFilterStem" and "TokenfilterStopWord" * table.token_filters = ["TokenFilterStem", "TokenFilterStopWord"] * * @overload token_filters=(token_filters) * @param token_filters [::Array<String>] Token filter names. */ static VALUE rb_grn_table_key_support_set_token_filters (VALUE self, VALUE rb_token_filters) { grn_ctx *context; grn_obj *table; grn_obj token_filters; grn_rc rc; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, GRN_ID_NIL); RVAL2GRNPVECTOR(rb_token_filters, context, &token_filters); rc = grn_obj_set_info(context, table, GRN_INFO_TOKEN_FILTERS, &token_filters); grn_obj_unlink(context, &token_filters); rb_grn_context_check(context, self); rb_grn_rc_check(rc, self); return Qnil; }
static VALUE rb_grn_table_key_support_inspect_content (VALUE self, VALUE inspected) { RbGrnTableKeySupport *rb_grn_table; grn_ctx *context = NULL; grn_obj *table; rb_grn_table = SELF(self); if (!rb_grn_table) return inspected; rb_grn_table_key_support_deconstruct(SELF(self), &table, &context, NULL, NULL, NULL, NULL, NULL, NULL, NULL); if (!table) return inspected; if (!context) return inspected; { grn_obj value; grn_encoding encoding; rb_str_cat2(inspected, ", "); rb_str_cat2(inspected, "encoding: <"); GRN_OBJ_INIT(&value, GRN_BULK, 0, GRN_ID_NIL); grn_obj_get_info(context, table, GRN_INFO_ENCODING, &value); encoding = *((grn_encoding *)GRN_BULK_HEAD(&value)); grn_obj_unlink(context, &value); if (context->rc == GRN_SUCCESS) { rb_str_concat(inspected, rb_inspect(GRNENCODING2RVAL(encoding))); } else { rb_str_cat2(inspected, "invalid"); } rb_str_cat2(inspected, ">"); } { grn_obj *default_tokenizer; rb_str_cat2(inspected, ", "); rb_str_cat2(inspected, "default_tokenizer: "); default_tokenizer = grn_obj_get_info(context, table, GRN_INFO_DEFAULT_TOKENIZER, NULL); if (default_tokenizer) { rb_grn_object_inspect_object_content_name(inspected, context, default_tokenizer); } else { rb_str_cat2(inspected, "(nil)"); } } { grn_obj *normalizer; rb_str_cat2(inspected, ", "); rb_str_cat2(inspected, "normalizer: "); normalizer = grn_obj_get_info(context, table, GRN_INFO_NORMALIZER, NULL); if (normalizer) { rb_grn_object_inspect_object_content_name(inspected, context, normalizer); } else { rb_str_cat2(inspected, "(nil)"); } } return inspected; }