grn_rc grn_snip_add_cond(grn_ctx *ctx, grn_snip *snip, const char *keyword, unsigned int keyword_len, const char *opentag, unsigned int opentag_len, const char *closetag, unsigned int closetag_len) { grn_rc rc; int copy_tag; snip_cond *cond; unsigned int norm_blen; if (!snip || !keyword || !keyword_len || snip->cond_len >= MAX_SNIP_COND_COUNT) { return GRN_INVALID_ARGUMENT; } cond = snip->cond + snip->cond_len; if ((rc = grn_snip_cond_init(ctx, cond, keyword, keyword_len, snip->encoding, snip->normalizer, snip->flags))) { return rc; } grn_string_get_normalized(ctx, cond->keyword, NULL, &norm_blen, NULL); if (norm_blen > snip->width) { grn_snip_cond_close(ctx, cond); return GRN_INVALID_ARGUMENT; } copy_tag = snip->flags & GRN_SNIP_COPY_TAG; rc = grn_snip_cond_set_tag(ctx, &(cond->opentag), &(cond->opentag_len), opentag, opentag_len, snip->defaultopentag, snip->defaultopentag_len, copy_tag); if (rc) { grn_snip_cond_close(ctx, cond); return rc; } rc = grn_snip_cond_set_tag(ctx, &(cond->closetag), &(cond->closetag_len), closetag, closetag_len, snip->defaultclosetag, snip->defaultclosetag_len, copy_tag); if (rc) { if (opentag && copy_tag) { GRN_FREE((void *)cond->opentag); } grn_snip_cond_close(ctx, cond); return rc; } snip->cond_len++; return GRN_SUCCESS; }
/* TODO: delete overlapping logic with exec_query */ static grn_rc scan_query(grn_ctx *ctx, grn_query *q, grn_str *nstr, grn_id section, grn_cell *c, snip_cond **sc, grn_operator op, int flags, int *found, int *score) { int _found = 0, _score = 0; grn_cell *e, *ope = NIL; grn_operator op0 = GRN_OP_OR, *opp = &op0, op1 = q->default_op; while (c != NIL) { POP(e, c); switch (e->header.type) { case GRN_CELL_OP : if (opp == &op0 && e->u.op.op == GRN_OP_BUT) { POP(e, c); } else { ope = e; op1 = ope->u.op.op; } continue; case GRN_CELL_STR : if (ope != NIL) { q->opt.mode = ope->u.op.mode == -1 ? q->default_mode : ope->u.op.mode; q->opt.max_interval = q->opt.similarity_threshold = ope->u.op.option; if (!q->opt.weight_vector) { q->opt.vector_size = ope->u.op.weight + q->weight_offset; } } else { q->opt.mode = q->default_mode; q->opt.max_interval = DEFAULT_MAX_INTERVAL; q->opt.similarity_threshold = DEFAULT_SIMILARITY_THRESHOLD; if (!q->opt.weight_vector) { q->opt.vector_size = DEFAULT_WEIGHT + q->weight_offset; } } if ((flags & GRN_QUERY_SCAN_ALLOCCONDS)) { grn_rc rc; /* NOTE: GRN_SNIP_NORMALIZE = GRN_QUERY_SCAN_NORMALIZE */ if ((rc = grn_snip_cond_init(ctx, *sc, e->u.b.value, e->u.b.size, q->encoding, flags & GRN_SNIP_NORMALIZE))) { return rc; } } else { grn_snip_cond_reinit(*sc); } scan_keyword(*sc, nstr, section, *opp, &q->opt, &_found, &_score); (*sc)++; break; case GRN_CELL_LIST : scan_query(ctx, q, nstr, section, e, sc, *opp, flags, &_found, &_score); break; default : GRN_LOG(ctx, GRN_LOG_NOTICE, "invalid object assigned in query! (%d)", e->header.type); break; } opp = &op1; ope = NIL; op1 = q->default_op; } switch (op) { case GRN_OP_OR : *found |= _found; *score += _score; break; case GRN_OP_AND : *found &= _found; *score += _score; break; case GRN_OP_BUT : *found &= !_found; break; case GRN_OP_ADJUST : *score += _score; break; default : break; } return GRN_SUCCESS; }