VALUE rb_grn_vector_to_ruby_object (grn_ctx *context, grn_obj *vector) { VALUE array; grn_obj value; unsigned int i, n; if (!vector) return Qnil; GRN_VOID_INIT(&value); n = grn_vector_size(context, vector); array = rb_ary_new2(n); for (i = 0; i < n; i++) { const char *_value; unsigned int weight, length; grn_id domain; length = grn_vector_get_element(context, vector, i, &_value, &weight, &domain); grn_obj_reinit(context, &value, domain, 0); grn_bulk_write(context, &value, _value, length); rb_ary_push(array, GRNOBJ2RVAL(Qnil, context, &value, Qnil)); } GRN_OBJ_FIN(context, &value); return array; }
static void command_schema_output_plugins(grn_ctx *ctx) { grn_obj plugin_names; unsigned int i, n; GRN_TEXT_INIT(&plugin_names, GRN_OBJ_VECTOR); grn_plugin_get_names(ctx, &plugin_names); grn_ctx_output_cstr(ctx, "plugins"); n = grn_vector_size(ctx, &plugin_names); grn_ctx_output_map_open(ctx, "plugins", n); for (i = 0; i < n; i++) { const char *name; unsigned int name_size; name_size = grn_vector_get_element(ctx, &plugin_names, i, &name, NULL, NULL); grn_ctx_output_str(ctx, name, name_size); grn_ctx_output_map_open(ctx, "plugin", 1); grn_ctx_output_cstr(ctx, "name"); grn_ctx_output_str(ctx, name, name_size); grn_ctx_output_map_close(ctx); } grn_ctx_output_map_close(ctx); GRN_OBJ_FIN(ctx, &plugin_names); }
static grn_bool exec_match_vector_bulk(grn_ctx *ctx, grn_obj *vector, grn_obj *query) { grn_bool matched = GRN_FALSE; unsigned int i, size; grn_obj element; size = grn_vector_size(ctx, vector); GRN_VOID_INIT(&element); for (i = 0; i < size; i++) { const char *content; unsigned int content_size; grn_id domain_id; content_size = grn_vector_get_element(ctx, vector, i, &content, NULL, &domain_id); grn_obj_reinit(ctx, &element, domain_id, 0); grn_bulk_write(ctx, &element, content, content_size); if (grn_operator_exec_equal(ctx, &element, query)) { matched = GRN_TRUE; break; } } GRN_OBJ_FIN(ctx, &element); return matched; }
static grn_obj * func_vector_size(grn_ctx *ctx, int n_args, grn_obj **args, grn_user_data *user_data) { grn_obj *target; unsigned int size; grn_obj *grn_size; if (n_args != 1) { GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "vector_size(): wrong number of arguments (%d for 1)", n_args); return NULL; } target = args[0]; switch (target->header.type) { case GRN_VECTOR : case GRN_PVECTOR : case GRN_UVECTOR : size = grn_vector_size(ctx, target); break; default : { grn_obj inspected; GRN_TEXT_INIT(&inspected, 0); grn_inspect(ctx, target, &inspected); GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "vector_size(): target object must be vector: <%.*s>", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); return NULL; } break; } grn_size = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, 0); if (!grn_size) { return NULL; } GRN_UINT32_SET(ctx, grn_size, size); return grn_size; }
static grn_highlighter * func_highlight_html_create_highlighter(grn_ctx *ctx, grn_obj *expression) { grn_highlighter *highlighter; grn_obj *condition_ptr = NULL; grn_obj *condition = NULL; highlighter = grn_highlighter_open(ctx); condition_ptr = grn_expr_get_var(ctx, expression, GRN_SELECT_INTERNAL_VAR_CONDITION, strlen(GRN_SELECT_INTERNAL_VAR_CONDITION)); if (condition_ptr) { condition = GRN_PTR_VALUE(condition_ptr); } if (condition) { size_t i, n_keywords; grn_obj current_keywords; GRN_TEXT_INIT(¤t_keywords, GRN_OBJ_VECTOR); grn_expr_get_keywords(ctx, condition, ¤t_keywords); n_keywords = grn_vector_size(ctx, ¤t_keywords); for (i = 0; i < n_keywords; i++) { const char *keyword; unsigned int keyword_size; keyword_size = grn_vector_get_element(ctx, ¤t_keywords, i, &keyword, NULL, NULL); grn_highlighter_add_keyword(ctx, highlighter, keyword, keyword_size); } GRN_OBJ_FIN(ctx, ¤t_keywords); } return highlighter; }
/* grn_ts_writer_build() builds output expresions. */ static grn_rc grn_ts_writer_build(grn_ctx *ctx, grn_ts_writer *writer, grn_obj *table) { size_t i, n_names = grn_vector_size(ctx, &writer->name_buf); if (!n_names) { return GRN_SUCCESS; } writer->names = GRN_MALLOCN(grn_ts_str, n_names); if (!writer->names) { GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, sizeof(grn_ts_str), n_names); } writer->exprs = GRN_MALLOCN(grn_ts_expr *, n_names); if (!writer->exprs) { GRN_TS_ERR_RETURN(GRN_NO_MEMORY_AVAILABLE, "GRN_MALLOCN failed: %" GRN_FMT_SIZE " x %" GRN_FMT_SIZE, sizeof(grn_ts_expr *), n_names); } for (i = 0; i < n_names; i++) { grn_rc rc; grn_ts_expr *new_expr; const char *name_ptr; size_t name_size = grn_vector_get_element(ctx, &writer->name_buf, i, &name_ptr, NULL, NULL); rc = grn_ts_expr_parser_parse(ctx, writer->parser, (grn_ts_str){ name_ptr, name_size }, &new_expr); if (rc != GRN_SUCCESS) { return rc; } writer->names[i].ptr = name_ptr; writer->names[i].size = name_size; writer->exprs[i] = new_expr; writer->n_exprs++; } return GRN_SUCCESS; }
static grn_rc sequential_fuzzy_search(grn_ctx *ctx, grn_obj *table, grn_obj *column, grn_obj *query, uint32_t max_distance, uint32_t prefix_match_size, uint32_t max_expansion, int flags, grn_obj *res, grn_operator op) { grn_table_cursor *tc; char *sx = GRN_TEXT_VALUE(query); char *ex = GRN_BULK_CURR(query); if (op == GRN_OP_AND) { tc = grn_table_cursor_open(ctx, res, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_ID); } else { tc = grn_table_cursor_open(ctx, table, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_BY_ID); } if (tc) { grn_id id; grn_obj value; score_heap *heap; int i, n; GRN_TEXT_INIT(&value, 0); heap = score_heap_open(ctx, SCORE_HEAP_SIZE); if (!heap) { grn_table_cursor_close(ctx, tc); grn_obj_unlink(ctx, &value); return GRN_NO_MEMORY_AVAILABLE; } while ((id = grn_table_cursor_next(ctx, tc))) { unsigned int distance = 0; grn_obj *domain; GRN_BULK_REWIND(&value); grn_obj_get_value(ctx, column, id, &value); domain = grn_ctx_at(ctx, ((&value))->header.domain); if ((&(value))->header.type == GRN_VECTOR) { n = grn_vector_size(ctx, &value); for (i = 0; i < n; i++) { unsigned int length; const char *vector_value = NULL; length = grn_vector_get_element(ctx, &value, i, &vector_value, NULL, NULL); if (!prefix_match_size || (prefix_match_size > 0 && length >= prefix_match_size && !memcmp(sx, vector_value, prefix_match_size))) { distance = calc_edit_distance(ctx, sx, ex, (char *)vector_value, (char *)vector_value + length, flags); if (distance <= max_distance) { score_heap_push(ctx, heap, id, distance); break; } } } } else if ((&(value))->header.type == GRN_UVECTOR && grn_obj_is_table(ctx, domain)) { n = grn_vector_size(ctx, &value); for (i = 0; i < n; i++) { grn_id rid; char key_name[GRN_TABLE_MAX_KEY_SIZE]; int key_length; rid = grn_uvector_get_element(ctx, &value, i, NULL); key_length = grn_table_get_key(ctx, domain, rid, key_name, GRN_TABLE_MAX_KEY_SIZE); if (!prefix_match_size || (prefix_match_size > 0 && key_length >= prefix_match_size && !memcmp(sx, key_name, prefix_match_size))) { distance = calc_edit_distance(ctx, sx, ex, key_name, key_name + key_length, flags); if (distance <= max_distance) { score_heap_push(ctx, heap, id, distance); break; } } } } else { if (grn_obj_is_reference_column(ctx, column)) { grn_id rid; char key_name[GRN_TABLE_MAX_KEY_SIZE]; int key_length; rid = GRN_RECORD_VALUE(&value); key_length = grn_table_get_key(ctx, domain, rid, key_name, GRN_TABLE_MAX_KEY_SIZE); if (!prefix_match_size || (prefix_match_size > 0 && key_length >= prefix_match_size && !memcmp(sx, key_name, prefix_match_size))) { distance = calc_edit_distance(ctx, sx, ex, key_name, key_name + key_length, flags); if (distance <= max_distance) { score_heap_push(ctx, heap, id, distance); } } } else { if (!prefix_match_size || (prefix_match_size > 0 && GRN_TEXT_LEN(&value) >= prefix_match_size && !memcmp(sx, GRN_TEXT_VALUE(&value), prefix_match_size))) { distance = calc_edit_distance(ctx, sx, ex, GRN_TEXT_VALUE(&value), GRN_BULK_CURR(&value), flags); if (distance <= max_distance) { score_heap_push(ctx, heap, id, distance); } } } } grn_obj_unlink(ctx, domain); } grn_table_cursor_close(ctx, tc); grn_obj_unlink(ctx, &value); for (i = 0; i < heap->n_entries; i++) { if (max_expansion > 0 && i >= max_expansion) { break; } { grn_posting posting; posting.rid = heap->nodes[i].id; posting.sid = 1; posting.pos = 0; posting.weight = max_distance - heap->nodes[i].score; grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); } } grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); score_heap_close(ctx, heap); } return GRN_SUCCESS; }
/* * It gets a value of variable size column value for the record that * ID is _id_. * * @example Gets weight vector value * Groonga::Schema.define do |schema| * schema.create_table("Products", * :type => :patricia_trie, * :key_type => "ShortText") do |table| * # This is weight vector. * # ":with_weight => true" is important to store weight value. * table.short_text("tags", * :type => :vector, * :with_weight => true) * end * end * * products = Groonga["Products"] * rroonga = products.add("Rroonga") * rroonga.tags = [ * { * :value => "ruby", * :weight => 100, * }, * { * :value => "groonga", * :weight => 10, * }, * ] * * p rroonga.tags * # => [ * # {:value => "ruby", :weight => 100}, * # {:value => "groonga", :weight => 10} * # ] * * @overload [](id) * @param [Integer, Record] id The record ID. * @return [Array<Hash<Symbol, String>>] An array of value if the column * is a weight vector column. * Each value is a Hash like the following form: * * <pre> * { * :value => [KEY], * :weight => [WEIGHT], * } * </pre> * * @[KEY]@ is the key of the table that is specified as range on * creating the weight vector. * * @[WEIGHT]@ is a positive integer. * * @return [::Object] See {Groonga::Object#[]} for columns except * weight vector column. * * @since 4.0.1. */ static VALUE rb_grn_variable_size_column_array_reference (VALUE self, VALUE rb_id) { grn_ctx *context = NULL; grn_obj *column, *range; grn_id id; grn_obj *value; VALUE rb_value; VALUE rb_range; unsigned int i, n; rb_grn_variable_size_column_deconstruct(SELF(self), &column, &context, NULL, NULL, &value, NULL, NULL, &range); if (!(column->header.flags & GRN_OBJ_WITH_WEIGHT)) { return rb_call_super(1, &rb_id); } id = RVAL2GRNID(rb_id, context, range, self); grn_obj_reinit(context, value, value->header.domain, value->header.flags | GRN_OBJ_VECTOR); grn_obj_get_value(context, column, id, value); rb_grn_context_check(context, self); rb_range = GRNTABLE2RVAL(context, range, GRN_FALSE); n = grn_vector_size(context, value); rb_value = rb_ary_new2(n); for (i = 0; i < n; i++) { VALUE rb_element_value; unsigned int weight = 0; grn_id domain; VALUE rb_element; if (value->header.type == GRN_UVECTOR) { grn_id id; id = grn_uvector_get_element(context, value, i, &weight); rb_element_value = rb_grn_record_new(rb_range, id, Qnil); } else { const char *element_value; unsigned int element_value_length; element_value_length = grn_vector_get_element(context, value, i, &element_value, &weight, &domain); rb_element_value = rb_str_new(element_value, element_value_length); } rb_element = rb_hash_new(); rb_hash_aset(rb_element, ID2SYM(rb_intern("value")), rb_element_value); rb_hash_aset(rb_element, ID2SYM(rb_intern("weight")), UINT2NUM(weight)); rb_ary_push(rb_value, rb_element); } return rb_value; }
static grn_bool exec_equal(grn_ctx *ctx, grn_obj *x, grn_obj *y) { switch (x->header.type) { case GRN_BULK : if (y->header.type == GRN_BULK) { grn_bool is_equal = GRN_FALSE; DO_EQ(x, y, is_equal); return is_equal; } else { return GRN_FALSE; } break; case GRN_VECTOR : if (y->header.type == GRN_VECTOR) { grn_bool is_equal = GRN_TRUE; unsigned int x_size = grn_vector_size(ctx, x); unsigned int y_size = grn_vector_size(ctx, y); unsigned int i; grn_obj x_element; grn_obj y_element; if (x_size != y_size) { return GRN_FALSE; } GRN_VOID_INIT(&x_element); GRN_VOID_INIT(&y_element); for (i = 0; i < x_size; i++) { const char *x_value; unsigned int x_size; unsigned int x_weight; grn_id x_domain; const char *y_value; unsigned int y_size; unsigned int y_weight; grn_id y_domain; x_size = grn_vector_get_element(ctx, x, i, &x_value, &x_weight, &x_domain); y_size = grn_vector_get_element(ctx, y, i, &y_value, &y_weight, &y_domain); if (x_weight != y_weight) { is_equal = GRN_FALSE; break; } grn_obj_reinit(ctx, &x_element, x_domain, 0); grn_bulk_write(ctx, &x_element, x_value, x_size); grn_obj_reinit(ctx, &y_element, y_domain, 0); grn_bulk_write(ctx, &y_element, y_value, y_size); DO_EQ((&x_element), (&y_element), is_equal); if (!is_equal) { break; } } GRN_OBJ_FIN(ctx, &x_element); GRN_OBJ_FIN(ctx, &y_element); return is_equal; } else { return GRN_FALSE; } break; case GRN_UVECTOR : if (y->header.type == GRN_UVECTOR) { grn_bool is_equal = GRN_TRUE; unsigned int x_size = grn_vector_size(ctx, x); unsigned int y_size = grn_vector_size(ctx, y); unsigned int i; grn_obj x_element; grn_obj y_element; unsigned int x_element_size = grn_uvector_element_size(ctx, x); unsigned int y_element_size = grn_uvector_element_size(ctx, y); if (x_size != y_size) { return GRN_FALSE; } GRN_OBJ_INIT(&x_element, GRN_BULK, 0, x->header.domain); GRN_OBJ_INIT(&y_element, GRN_BULK, 0, y->header.domain); for (i = 0; i < x_size; i++) { const char *x_value; const char *y_value; x_value = GRN_BULK_HEAD(x) + (x_element_size * i); y_value = GRN_BULK_HEAD(y) + (y_element_size * i); GRN_BULK_REWIND(&x_element); GRN_BULK_REWIND(&y_element); grn_bulk_write(ctx, &x_element, x_value, x_element_size); grn_bulk_write(ctx, &y_element, y_value, y_element_size); DO_EQ((&x_element), (&y_element), is_equal); if (!is_equal) { break; } } GRN_OBJ_FIN(ctx, &x_element); GRN_OBJ_FIN(ctx, &y_element); return is_equal; } else { return GRN_FALSE; } break; default : return GRN_FALSE; } }
static grn_bool exec_regexp_vector_bulk(grn_ctx *ctx, grn_obj *vector, grn_obj *pattern) { #ifdef GRN_SUPPORT_REGEXP grn_obj *normalizer = NULL; grn_bool matched = GRN_FALSE; unsigned int i, size; OnigRegex regex; size = grn_vector_size(ctx, vector); if (size == 0) { return GRN_FALSE; } regex = grn_onigmo_new(ctx, GRN_TEXT_VALUE(pattern), GRN_TEXT_LEN(pattern), GRN_ONIGMO_OPTION_DEFAULT, GRN_ONIGMO_SYNTAX_DEFAULT, "[operator]"); if (!regex) { return GRN_FALSE; } normalizer = grn_ctx_get(ctx, GRN_NORMALIZER_AUTO_NAME, -1); for (i = 0; i < size; i++) { const char *content; unsigned int content_size; grn_id domain_id; grn_obj *norm_content; const char *norm_content_raw; unsigned int norm_content_raw_length_in_bytes; content_size = grn_vector_get_element(ctx, vector, i, &content, NULL, &domain_id); if (content_size == 0) { continue; } norm_content = grn_string_open(ctx, content, content_size, normalizer, 0); grn_string_get_normalized(ctx, norm_content, &norm_content_raw, &norm_content_raw_length_in_bytes, NULL); matched = regexp_is_match(ctx, regex, norm_content_raw, norm_content_raw_length_in_bytes); grn_obj_unlink(ctx, norm_content); if (matched) { break; } } grn_obj_unlink(ctx, normalizer); onig_free(regex); return matched; #else /* GRN_SUPPORT_REGEXP */ return GRN_FALSE; #endif /* GRN_SUPPORT_REGEXP */ }
static grn_obj * command_tag_synonym(grn_ctx *ctx, GNUC_UNUSED int nargs, GNUC_UNUSED grn_obj **args, GNUC_UNUSED grn_user_data *user_data) { GNUC_UNUSED grn_obj *flags = grn_ctx_pop(ctx); grn_obj *newvalue = grn_ctx_pop(ctx); grn_obj *oldvalue = grn_ctx_pop(ctx); GNUC_UNUSED grn_obj *id = grn_ctx_pop(ctx); grn_obj buf; grn_obj record; grn_obj *domain; grn_obj *table; grn_obj *column; int i,n; if (GRN_BULK_VSIZE(newvalue) == 0 || GRN_INT32_VALUE(flags) == 0) { return NULL; } table = grn_ctx_at(ctx, oldvalue->header.domain); if (table && !is_table(table)) { GRN_PLUGIN_LOG(ctx, GRN_LOG_WARNING, "[tag-synonym] " "hooked column must be reference type"); return NULL; } column = grn_obj_column(ctx, table, SYNONYM_COLUMN_NAME, SYNONYM_COLUMN_NAME_LEN); if (!column) { GRN_PLUGIN_LOG(ctx, GRN_LOG_WARNING, "[tag-synonym] " "couldn't open synonym column"); return NULL; } GRN_TEXT_INIT(&buf, 0); domain = grn_ctx_at(ctx, newvalue->header.domain); if (domain && is_string(domain)) { GRN_RECORD_INIT(&record, GRN_OBJ_VECTOR, oldvalue->header.domain); grn_table_tokenize(ctx, table, GRN_TEXT_VALUE(newvalue), GRN_TEXT_LEN(newvalue), &record, GRN_TRUE); } else if (newvalue->header.type == GRN_UVECTOR) { record = *newvalue; } if (is_string(domain) || newvalue->header.type == GRN_UVECTOR) { grn_obj value; GRN_RECORD_INIT(newvalue, GRN_OBJ_VECTOR, oldvalue->header.domain); GRN_UINT32_INIT(&value, 0); n = grn_vector_size(ctx, &record); for (i = 0; i < n; i++) { grn_id tid; tid = grn_uvector_get_element(ctx, &record, i, NULL); GRN_BULK_REWIND(&value); grn_obj_get_value(ctx, column, tid, &value); if (GRN_UINT32_VALUE(&value)) { GRN_PLUGIN_LOG(ctx, GRN_LOG_INFO, "[tag-synonym] " "changed: tid %d -> %d", tid, GRN_UINT32_VALUE(&value)); tid = GRN_UINT32_VALUE(&value); } grn_uvector_add_element(ctx, newvalue, tid, 0); } grn_obj_unlink(ctx, &value); } else { grn_id tid; grn_obj value; tid = GRN_RECORD_VALUE(newvalue); GRN_UINT32_INIT(&value, 0); grn_obj_get_value(ctx, column, tid, &value); if (GRN_UINT32_VALUE(&value)) { GRN_PLUGIN_LOG(ctx, GRN_LOG_INFO, "[tag-synonym] " "changed: tid %d -> %d", tid, GRN_UINT32_VALUE(&value)); tid = GRN_UINT32_VALUE(&value); GRN_BULK_REWIND(newvalue); GRN_RECORD_SET(ctx, newvalue, tid); } grn_obj_unlink(ctx, &value); } grn_obj_unlink(ctx, &buf); return NULL; }
static grn_obj * func_vector_slice(grn_ctx *ctx, int n_args, grn_obj **args, grn_user_data *user_data) { grn_obj *target; grn_obj *from_raw = NULL; grn_obj *length_raw = NULL; int64_t from = 0; int64_t length = -1; uint32_t to = 0; uint32_t size = 0; grn_obj *slice; if (n_args < 2 || n_args > 3) { GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "vector_slice(): wrong number of arguments (%d for 2..3)", n_args); return NULL; } target = args[0]; from_raw = args[1]; if (n_args == 3) { length_raw = args[2]; } switch (target->header.type) { case GRN_VECTOR : case GRN_PVECTOR : case GRN_UVECTOR : size = grn_vector_size(ctx, target); break; default : { grn_obj inspected; GRN_TEXT_INIT(&inspected, 0); grn_inspect(ctx, target, &inspected); GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "vector_slice(): target object must be vector: <%.*s>", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); return NULL; } break; } if (!grn_type_id_is_number_family(ctx, from_raw->header.domain)) { grn_obj inspected; GRN_TEXT_INIT(&inspected, 0); grn_inspect(ctx, &inspected, from_raw); GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "vector_slice(): from must be a number: <%.*s>", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); return NULL; } if (from_raw->header.domain == GRN_DB_INT32) { from = GRN_INT32_VALUE(from_raw); } else if (from_raw->header.domain == GRN_DB_INT64) { from = GRN_INT64_VALUE(from_raw); } else { grn_obj buffer; grn_rc rc; GRN_INT64_INIT(&buffer, 0); rc = grn_obj_cast(ctx, from_raw, &buffer, GRN_FALSE); if (rc == GRN_SUCCESS) { from = GRN_INT64_VALUE(&buffer); } GRN_OBJ_FIN(ctx, &buffer); if (rc != GRN_SUCCESS) { grn_obj inspected; GRN_TEXT_INIT(&inspected, 0); grn_inspect(ctx, &inspected, from_raw); GRN_PLUGIN_ERROR(ctx, rc, "vector_slice(): " "failed to cast from value to number: <%.*s>", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); return NULL; } } if (length_raw) { if (!grn_type_id_is_number_family(ctx, length_raw->header.domain)) { grn_obj inspected; GRN_TEXT_INIT(&inspected, 0); grn_inspect(ctx, &inspected, length_raw); GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, "vector_slice(): length must be a number: <%.*s>", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); return NULL; } if (length_raw->header.domain == GRN_DB_INT32) { length = GRN_INT32_VALUE(length_raw); } else if (length_raw->header.domain == GRN_DB_INT64) { length = GRN_INT64_VALUE(length_raw); } else { grn_obj buffer; grn_rc rc; GRN_INT64_INIT(&buffer, 0); rc = grn_obj_cast(ctx, length_raw, &buffer, GRN_FALSE); if (rc == GRN_SUCCESS) { length = GRN_INT64_VALUE(&buffer); } GRN_OBJ_FIN(ctx, &buffer); if (rc != GRN_SUCCESS) { grn_obj inspected; GRN_TEXT_INIT(&inspected, 0); grn_inspect(ctx, &inspected, length_raw); GRN_PLUGIN_ERROR(ctx, rc, "vector_slice(): " "failed to cast length value to number: <%.*s>", (int)GRN_TEXT_LEN(&inspected), GRN_TEXT_VALUE(&inspected)); GRN_OBJ_FIN(ctx, &inspected); return NULL; } } } slice = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, GRN_OBJ_VECTOR); if (!slice) { return NULL; } if (target->header.flags & GRN_OBJ_WITH_WEIGHT) { slice->header.flags |= GRN_OBJ_WITH_WEIGHT; } if (length < 0) { length = size + length + 1; } if (length > size) { length = size; } if (length <= 0) { return slice; } while (from < 0) { from += size; } to = from + length; if (to > size) { to = size; } switch (target->header.type) { case GRN_VECTOR : { unsigned int i; for (i = from; i < to; i++) { const char *content; unsigned int content_length; unsigned int weight; grn_id domain; content_length = grn_vector_get_element(ctx, target, i, &content, &weight, &domain); grn_vector_add_element(ctx, slice, content, content_length, weight, domain); } } break; case GRN_PVECTOR : { unsigned int i; for (i = from; i < to; i++) { grn_obj *element = GRN_PTR_VALUE_AT(target, i); GRN_PTR_PUT(ctx, slice, element); } } break; case GRN_UVECTOR : { unsigned int i; for (i = from; i < to; i++) { grn_id id; unsigned int weight; id = grn_uvector_get_element(ctx, target, i, &weight); grn_uvector_add_element(ctx, slice, id, weight); } } break; } return slice; }
void grn_output_obj(grn_ctx *ctx, grn_obj *outbuf, grn_content_type output_type, grn_obj *obj, grn_obj_format *format) { grn_obj buf; GRN_TEXT_INIT(&buf, 0); switch (obj->header.type) { case GRN_BULK : switch (obj->header.domain) { case GRN_DB_VOID : grn_output_void(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); break; case GRN_DB_SHORT_TEXT : case GRN_DB_TEXT : case GRN_DB_LONG_TEXT : grn_output_str(ctx, outbuf, output_type, GRN_BULK_HEAD(obj), GRN_BULK_VSIZE(obj)); break; case GRN_DB_BOOL : grn_output_bool(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0); break; case GRN_DB_INT8 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT8_VALUE(obj) : 0); break; case GRN_DB_UINT8 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT8_VALUE(obj) : 0); break; case GRN_DB_INT16 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT16_VALUE(obj) : 0); break; case GRN_DB_UINT16 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT16_VALUE(obj) : 0); break; case GRN_DB_INT32 : grn_output_int32(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT32_VALUE(obj) : 0); break; case GRN_DB_UINT32 : grn_output_int64(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT32_VALUE(obj) : 0); break; case GRN_DB_INT64 : grn_output_int64(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0); break; case GRN_DB_UINT64 : grn_output_uint64(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_UINT64_VALUE(obj) : 0); break; case GRN_DB_FLOAT : grn_output_float(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_FLOAT_VALUE(obj) : 0); break; case GRN_DB_TIME : grn_output_time(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? GRN_INT64_VALUE(obj) : 0); break; case GRN_DB_TOKYO_GEO_POINT : case GRN_DB_WGS84_GEO_POINT : grn_output_geo_point(ctx, outbuf, output_type, GRN_BULK_VSIZE(obj) ? (grn_geo_point *)GRN_BULK_HEAD(obj) : NULL); break; default : if (format) { int j; int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns); for (j = 0; j < ncolumns; j++) { grn_id range_id; grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); GRN_BULK_REWIND(&buf); grn_column_name_(ctx, columns[j], &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); /* column range */ range_id = grn_obj_get_range(ctx, columns[j]); if (range_id == GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, outbuf, "null"); } else { int name_len; grn_obj *range_obj; char name_buf[GRN_TABLE_MAX_KEY_SIZE]; range_obj = grn_ctx_at(ctx, range_id); name_len = grn_obj_name(ctx, range_obj, name_buf, GRN_TABLE_MAX_KEY_SIZE); GRN_BULK_REWIND(&buf); GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns); for (j = 0; j < ncolumns; j++) { grn_text_atoj_o(ctx, outbuf, output_type, columns[j], obj); } grn_output_array_close(ctx, outbuf, output_type); } else { grn_obj *table = grn_ctx_at(ctx, obj->header.domain); grn_id id = *((grn_id *)GRN_BULK_HEAD(obj)); if (table && table->header.type != GRN_TABLE_NO_KEY) { grn_obj *accessor = grn_obj_column(ctx, table, "_key", 4); if (accessor) { grn_obj_get_value(ctx, accessor, id, &buf); grn_obj_unlink(ctx, accessor); } grn_output_obj(ctx, outbuf, output_type, &buf, format); } else { grn_output_int64(ctx, outbuf, output_type, id); } } break; } break; case GRN_UVECTOR : if (format) { int i, j; grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj); int ncolumns = GRN_BULK_VSIZE(&format->columns) / sizeof(grn_obj *); grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", -1); grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); grn_text_itoa(ctx, outbuf, ve - v); grn_output_array_close(ctx, outbuf, output_type); if (v < ve) { if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", -1); for (j = 0; j < ncolumns; j++) { grn_id range_id; grn_output_array_open(ctx, outbuf, output_type, "COLUMN", -1); GRN_BULK_REWIND(&buf); grn_column_name_(ctx, columns[j], &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); /* column range */ range_id = grn_obj_get_range(ctx, columns[j]); if (range_id == GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, outbuf, "null"); } else { int name_len; grn_obj *range_obj; char name_buf[GRN_TABLE_MAX_KEY_SIZE]; range_obj = grn_ctx_at(ctx, range_id); name_len = grn_obj_name(ctx, range_obj, name_buf, GRN_TABLE_MAX_KEY_SIZE); GRN_BULK_REWIND(&buf); GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_close(ctx, outbuf, output_type); } for (i = 0;; i++) { grn_output_array_open(ctx, outbuf, output_type, "HITS", -1); for (j = 0; j < ncolumns; j++) { GRN_BULK_REWIND(&buf); grn_obj_get_value(ctx, columns[j], *v, &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); v++; if (v < ve) { } else { break; } } } grn_output_array_close(ctx, outbuf, output_type); } else { grn_obj *range = grn_ctx_at(ctx, obj->header.domain); if (range && range->header.type == GRN_TYPE) { int value_size = ((struct _grn_type *)range)->obj.range; char *v = (char *)GRN_BULK_HEAD(obj), *ve = (char *)GRN_BULK_CURR(obj); grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); if (v < ve) { for (;;) { grn_obj value; GRN_OBJ_INIT(&value, GRN_BULK, 0, obj->header.domain); grn_bulk_write_from(ctx, &value, v, 0, value_size); grn_output_obj(ctx, outbuf, output_type, &value, NULL); v += value_size; if (v < ve) { } else { break; } } } grn_output_array_close(ctx, outbuf, output_type); } else { grn_id *v = (grn_id *)GRN_BULK_HEAD(obj), *ve = (grn_id *)GRN_BULK_CURR(obj); grn_output_array_open(ctx, outbuf, output_type, "VECTOR", ve - v); if (v < ve) { grn_obj key; GRN_OBJ_INIT(&key, GRN_BULK, 0, range->header.domain); for (;;) { if (range->header.type != GRN_TABLE_NO_KEY) { grn_table_get_key2(ctx, range, *v, &key); grn_output_obj(ctx, outbuf, output_type, &key, NULL); GRN_BULK_REWIND(&key); } else { grn_obj id; GRN_UINT32_INIT(&id, 0); GRN_UINT32_SET(ctx, &id, *v); grn_output_obj(ctx, outbuf, output_type, &id, NULL); GRN_OBJ_FIN(ctx, &id); } v++; if (v < ve) { } else { break; } } GRN_OBJ_FIN(ctx, &key); } grn_output_array_close(ctx, outbuf, output_type); } } break; case GRN_VECTOR : if (obj->header.domain == GRN_DB_VOID) { ERR(GRN_INVALID_ARGUMENT, "invalid obj->header.domain"); } if (format) { ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "cannot print GRN_VECTOR using grn_obj_format"); } else { unsigned int i, n; grn_obj value; GRN_VOID_INIT(&value); n = grn_vector_size(ctx, obj); grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); for (i = 0; i < n; i++) { const char *_value; unsigned int weight, length; grn_id domain; length = grn_vector_get_element(ctx, obj, i, &_value, &weight, &domain); if (domain != GRN_DB_VOID) { grn_obj_reinit(ctx, &value, domain, 0); } else { grn_obj_reinit(ctx, &value, obj->header.domain, 0); } grn_bulk_write(ctx, &value, _value, length); grn_output_obj(ctx, outbuf, output_type, &value, NULL); } grn_output_array_close(ctx, outbuf, output_type); GRN_OBJ_FIN(ctx, &value); } break; case GRN_PVECTOR : if (format) { ERR(GRN_FUNCTION_NOT_IMPLEMENTED, "cannot print GRN_PVECTOR using grn_obj_format"); } else { unsigned int i, n; grn_output_array_open(ctx, outbuf, output_type, "VECTOR", -1); n = GRN_BULK_VSIZE(obj) / sizeof(grn_obj *); for (i = 0; i < n; i++) { grn_obj *value; value = GRN_PTR_VALUE_AT(obj, i); grn_output_obj(ctx, outbuf, output_type, value, NULL); } grn_output_array_close(ctx, outbuf, output_type); } break; case GRN_TABLE_HASH_KEY : case GRN_TABLE_PAT_KEY : case GRN_TABLE_NO_KEY : case GRN_TABLE_VIEW : if (format) { int i, j; int ncolumns = GRN_BULK_VSIZE(&format->columns)/sizeof(grn_obj *); grn_obj **columns = (grn_obj **)GRN_BULK_HEAD(&format->columns); grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, format->offset, format->limit, GRN_CURSOR_ASCENDING); int resultset_size = -1; if (!tc) { ERRCLR(ctx); } #ifdef HAVE_MESSAGE_PACK resultset_size = 1; /* [NHITS, (COLUMNS), (HITS)] */ if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { resultset_size++; } resultset_size += format->limit; #endif grn_output_array_open(ctx, outbuf, output_type, "RESULTSET", resultset_size); grn_output_array_open(ctx, outbuf, output_type, "NHITS", 1); if (output_type == GRN_CONTENT_XML) { grn_text_itoa(ctx, outbuf, format->nhits); } else { grn_output_int32(ctx, outbuf, output_type, format->nhits); } grn_output_array_close(ctx, outbuf, output_type); if (format->flags & GRN_OBJ_FORMAT_WITH_COLUMN_NAMES) { grn_output_array_open(ctx, outbuf, output_type, "COLUMNS", ncolumns); for (j = 0; j < ncolumns; j++) { grn_id range_id; grn_output_array_open(ctx, outbuf, output_type, "COLUMN", 2); GRN_BULK_REWIND(&buf); grn_column_name_(ctx, columns[j], &buf); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); /* column range */ range_id = grn_obj_get_range(ctx, columns[j]); if (range_id == GRN_ID_NIL) { GRN_TEXT_PUTS(ctx, outbuf, "null"); } else { int name_len; grn_obj *range_obj; char name_buf[GRN_TABLE_MAX_KEY_SIZE]; range_obj = grn_ctx_at(ctx, range_id); name_len = grn_obj_name(ctx, range_obj, name_buf, GRN_TABLE_MAX_KEY_SIZE); GRN_BULK_REWIND(&buf); GRN_TEXT_PUT(ctx, &buf, name_buf, name_len); grn_output_obj(ctx, outbuf, output_type, &buf, NULL); } grn_output_array_close(ctx, outbuf, output_type); } grn_output_array_close(ctx, outbuf, output_type); } if (tc) { grn_obj id; GRN_TEXT_INIT(&id, 0); for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) { grn_output_array_open(ctx, outbuf, output_type, "HIT", ncolumns); for (j = 0; j < ncolumns; j++) { grn_text_atoj_o(ctx, outbuf, output_type, columns[j], &id); } grn_output_array_close(ctx, outbuf, output_type); } GRN_OBJ_FIN(ctx, &id); grn_table_cursor_close(ctx, tc); } grn_output_array_close(ctx, outbuf, output_type); } else { int i; grn_obj *column = grn_obj_column(ctx, obj, "_key", 4); grn_table_cursor *tc = grn_table_cursor_open(ctx, obj, NULL, 0, NULL, 0, 0, -1, GRN_CURSOR_ASCENDING); grn_output_array_open(ctx, outbuf, output_type, "HIT", -1); if (tc) { grn_obj id; GRN_TEXT_INIT(&id, 0); for (i = 0; !grn_table_cursor_next_o(ctx, tc, &id); i++) { /* todo: grn_text_atoj_o(ctx, outbuf, output_type, column, &id); */ GRN_BULK_REWIND(&buf); grn_obj_get_value_o(ctx, column, &id, &buf); grn_text_esc(ctx, outbuf, GRN_BULK_HEAD(&buf), GRN_BULK_VSIZE(&buf)); } GRN_OBJ_FIN(ctx, &id); grn_table_cursor_close(ctx, tc); } grn_output_array_close(ctx, outbuf, output_type); grn_obj_unlink(ctx, column); } break; } GRN_OBJ_FIN(ctx, &buf); }
static void command_schema_output_command(grn_ctx *ctx, const char *command_name, grn_obj *arguments) { grn_ctx_output_map_open(ctx, "command", 3); grn_ctx_output_cstr(ctx, "name"); grn_ctx_output_cstr(ctx, command_name); grn_ctx_output_cstr(ctx, "arguments"); { int i, n; n = grn_vector_size(ctx, arguments); grn_ctx_output_map_open(ctx, "arguments", n / 2); for (i = 0; i < n; i += 2) { const char *name; unsigned int name_size; const char *value; unsigned int value_size; name_size = grn_vector_get_element(ctx, arguments, i, &name, NULL, NULL); value_size = grn_vector_get_element(ctx, arguments, i + 1, &value, NULL, NULL); grn_ctx_output_str(ctx, name, name_size); grn_ctx_output_str(ctx, value, value_size); } grn_ctx_output_map_close(ctx); } grn_ctx_output_cstr(ctx, "command_line"); { int i, n; grn_obj command_line; GRN_TEXT_INIT(&command_line, 0); GRN_TEXT_PUTS(ctx, &command_line, command_name); n = grn_vector_size(ctx, arguments); for (i = 0; i < n; i += 2) { const char *name; unsigned int name_size; const char *value; unsigned int value_size; name_size = grn_vector_get_element(ctx, arguments, i, &name, NULL, NULL); value_size = grn_vector_get_element(ctx, arguments, i + 1, &value, NULL, NULL); grn_text_printf(ctx, &command_line, " --%.*s %.*s", name_size, name, value_size, value); } grn_ctx_output_str(ctx, GRN_TEXT_VALUE(&command_line), GRN_TEXT_LEN(&command_line)); GRN_OBJ_FIN(ctx, &command_line); } grn_ctx_output_map_close(ctx); }