예제 #1
0
파일: QueryParser.c 프로젝트: kidaa/lucy
static void
S_balance_parens(QueryParser *self, Vector *elems) {
    UNUSED_VAR(self);
    // Count paren balance, eliminate unbalanced right parens.
    int64_t paren_depth = 0;
    size_t i = 0;
    while (i < Vec_Get_Size(elems)) {
        ParserElem *elem = (ParserElem*)Vec_Fetch(elems, i);
        if (ParserElem_Get_Type(elem) == TOKEN_OPEN_PAREN) {
            paren_depth++;
        }
        else if (ParserElem_Get_Type(elem) == TOKEN_CLOSE_PAREN) {
            if (paren_depth > 0) {
                paren_depth--;
            }
            else {
                Vec_Excise(elems, i, 1);
                continue;
            }
        }
        i++;
    }

    // Insert implicit parens.
    while (paren_depth--) {
        ParserElem *elem = ParserElem_new(TOKEN_CLOSE_PAREN, NULL);
        Vec_Push(elems, (Obj*)elem);
    }
}
예제 #2
0
파일: QueryParser.c 프로젝트: kidaa/lucy
static void
S_discard_elems(Vector *elems, uint32_t type) {
    for (size_t i = Vec_Get_Size(elems); i--;) {
        ParserElem *elem = (ParserElem*)Vec_Fetch(elems, i);
        if (ParserElem_Get_Type(elem) == type) { Vec_Excise(elems, i, 1); }
    }
}
예제 #3
0
파일: HeatMap.c 프로젝트: rectang/lucy
Vector*
HeatMap_Flatten_Spans_IMP(HeatMap *self, Vector *spans) {
    const size_t num_spans = Vec_Get_Size(spans);
    UNUSED_VAR(self);

    if (!num_spans) {
        return Vec_new(0);
    }
    else {
        Vector *flattened = S_flattened_but_empty_spans(spans);
        const size_t num_raw_flattened = Vec_Get_Size(flattened);

        // Iterate over each of the source spans, contributing their scores to
        // any destination span that falls within range.
        size_t dest_tick = 0;
        for (size_t i = 0; i < num_spans; i++) {
            Span *source_span = (Span*)Vec_Fetch(spans, i);
            int32_t source_span_offset = Span_Get_Offset(source_span);
            int32_t source_span_len    = Span_Get_Length(source_span);
            int32_t source_span_end    = source_span_offset + source_span_len;

            // Get the location of the flattened span that shares the source
            // span's offset.
            for (; dest_tick < num_raw_flattened; dest_tick++) {
                Span *dest_span = (Span*)Vec_Fetch(flattened, dest_tick);
                if (Span_Get_Offset(dest_span) == source_span_offset) {
                    break;
                }
            }

            // Fill in scores.
            for (size_t j = dest_tick; j < num_raw_flattened; j++) {
                Span *dest_span = (Span*)Vec_Fetch(flattened, j);
                if (Span_Get_Offset(dest_span) == source_span_end) {
                    break;
                }
                else {
                    float new_weight = Span_Get_Weight(dest_span)
                                       + Span_Get_Weight(source_span);
                    Span_Set_Weight(dest_span, new_weight);
                }
            }
        }

        // Leave holes instead of spans that don't have any score.
        dest_tick = 0;
        for (size_t i = 0; i < num_raw_flattened; i++) {
            Span *span = (Span*)Vec_Fetch(flattened, i);
            if (Span_Get_Weight(span)) {
                Vec_Store(flattened, dest_tick++, INCREF(span));
            }
        }
        Vec_Excise(flattened, dest_tick, num_raw_flattened - dest_tick);

        return flattened;
    }
}
예제 #4
0
파일: QueryParser.c 프로젝트: kidaa/lucy
static void
S_parse_subqueries(QueryParser *self, Vector *elems) {
    const int32_t default_occur = QParser_IVARS(self)->default_occur;
    while (1) {
        // Work from the inside out, starting with the leftmost innermost
        // paren group.
        size_t left = SIZE_MAX;
        size_t right = SIZE_MAX;
        String *field = NULL;
        for (size_t i = 0, max = Vec_Get_Size(elems); i < max; i++) {
            ParserElem *elem = (ParserElem*)Vec_Fetch(elems, i);
            uint32_t type = ParserElem_Get_Type(elem);
            if (type == TOKEN_OPEN_PAREN) {
                left = i;
            }
            else if (type == TOKEN_CLOSE_PAREN) {
                right = i;
                break;
            }
            else if (type == TOKEN_FIELD && i < max - 1) {
                // If a field applies to an enclosing paren, pass it along.
                ParserElem *next_elem = (ParserElem*)Vec_Fetch(elems, i + 1);
                uint32_t next_type = ParserElem_Get_Type(next_elem);
                if (next_type == TOKEN_OPEN_PAREN) {
                    field = (String*)ParserElem_As(elem, STRING);
                }
            }
        }

        // Break out of loop when there are no parens left.
        if (right == SIZE_MAX) {
            break;
        }

        // Create the subquery.
        Vector *sub_elems = Vec_Slice(elems, left + 1, right - left - 1);
        Query *subquery = S_parse_subquery(self, sub_elems, field, true);
        ParserElem *new_elem = ParserElem_new(TOKEN_QUERY, (Obj*)subquery);
        if (default_occur == MUST) {
            ParserElem_Require(new_elem);
        }
        DECREF(sub_elems);

        // Replace the elements used to create the subquery with the subquery
        // itself.
        if (left > 0) {
            ParserElem *maybe_field = (ParserElem*)Vec_Fetch(elems, left - 1);
            uint32_t maybe_field_type = ParserElem_Get_Type(maybe_field);
            if (maybe_field_type == TOKEN_FIELD) {
                left -= 1;
            }
        }
        Vec_Excise(elems, left + 1, right - left);
        Vec_Store(elems, left, (Obj*)new_elem);
    }
}
예제 #5
0
파일: QueryParser.c 프로젝트: kidaa/lucy
static void
S_compose_or_queries(QueryParser *self, Vector *elems) {
    const int32_t default_occur = QParser_IVARS(self)->default_occur;

    for (uint32_t i = 0; i + 2 < Vec_Get_Size(elems); i++) {
        ParserElem *elem = (ParserElem*)Vec_Fetch(elems, i + 1);
        if (ParserElem_Get_Type(elem) == TOKEN_OR) {
            ParserElem   *preceding  = (ParserElem*)Vec_Fetch(elems, i);
            Vector       *children   = Vec_new(2);
            uint32_t      num_to_zap = 0;

            // Add first clause.
            Query *preceding_query = (Query*)ParserElem_As(preceding, QUERY);
            Vec_Push(children, INCREF(preceding_query));

            // Add following clauses.
            for (uint32_t j = i + 1, jmax = Vec_Get_Size(elems);
                 j < jmax;
                 j += 2, num_to_zap += 2
                ) {
                ParserElem *maybe_or  = (ParserElem*)Vec_Fetch(elems, j);
                ParserElem *following = (ParserElem*)Vec_Fetch(elems, j + 1);
                if (ParserElem_Get_Type(maybe_or) != TOKEN_OR) {
                    break;
                }
                else if (ParserElem_Get_Type(following) == TOKEN_QUERY) {
                    Query *next = (Query*)ParserElem_As(following, QUERY);
                    Vec_Push(children, INCREF(next));
                }
                else {
                    THROW(ERR, "Unexpected type: %u32",
                          ParserElem_Get_Type(following));
                }
            }
            Query *or_query = QParser_Make_OR_Query(self, children);
            ParserElem_Set_Value(preceding, (Obj*)or_query);
            if (default_occur == MUST) {
                ParserElem_Require(preceding);
            }
            DECREF(or_query);
            DECREF(children);

            Vec_Excise(elems, i + 1, num_to_zap);
        }
    }
}
예제 #6
0
파일: SortExternal.c 프로젝트: kidaa/lucy
static void
S_refill_buffer(SortExternal *self, SortExternalIVARS *ivars) {
    // Reset buffer vars.
    SortEx_Clear_Buffer(self);

    // Make sure all runs have at least one item in the buffer.
    uint32_t i = 0;
    while (i < Vec_Get_Size(ivars->runs)) {
        SortExternal *const run = (SortExternal*)Vec_Fetch(ivars->runs, i);
        if (SortEx_Buffer_Count(run) > 0 || SortEx_Refill(run) > 0) {
            i++; // Run has some elements, so keep.
        }
        else {
            Vec_Excise(ivars->runs, i, 1);
        }
    }

    // Absorb as many elems as possible from all runs into main buffer.
    if (Vec_Get_Size(ivars->runs)) {
        Obj **endpost = S_find_endpost(self, ivars);
        S_absorb_slices(self, ivars, endpost);
    }
}
예제 #7
0
파일: QueryParser.c 프로젝트: kidaa/lucy
static void
S_winnow_boolops(QueryParser *self, Vector *elems) {
    UNUSED_VAR(self);
    for (uint32_t i = 0; i < Vec_Get_Size(elems); i++) {
        ParserElem *elem = (ParserElem*)Vec_Fetch(elems, i);
        if (ParserElem_Get_Type(elem) != TOKEN_QUERY) {
            uint32_t num_to_zap = 0;
            ParserElem *preceding = (ParserElem*)Vec_Fetch(elems, i - 1);
            ParserElem *following = (ParserElem*)Vec_Fetch(elems, i + 1);
            if (!preceding || ParserElem_Get_Type(preceding) != TOKEN_QUERY) {
                num_to_zap = 1;
            }
            if (!following || ParserElem_Get_Type(following) != TOKEN_QUERY) {
                num_to_zap = 1;
            }
            for (uint32_t j = i + 1, jmax = Vec_Get_Size(elems); j < jmax; j++) {
                ParserElem *maybe = (ParserElem*)Vec_Fetch(elems, j);
                if (ParserElem_Get_Type(maybe) == TOKEN_QUERY) { break; }
                else { num_to_zap++; }
            }
            if (num_to_zap) { Vec_Excise(elems, i, num_to_zap); }
        }
    }
}
예제 #8
0
파일: QueryParser.c 프로젝트: kidaa/lucy
static Query*
S_parse_subquery(QueryParser *self, Vector *elems, String *default_field,
                 bool enclosed) {
    if (Vec_Get_Size(elems)) {
        ParserElem *first = (ParserElem*)Vec_Fetch(elems, 0);
        if (ParserElem_Get_Type(first) == TOKEN_OPEN_PAREN) {
            enclosed = true;
            Vec_Excise(elems, 0, 1);
            DECREF(Vec_Pop(elems));
        }
    }
    S_compose_inner_queries(self, elems, default_field);
    S_discard_elems(elems, TOKEN_FIELD);
    S_discard_elems(elems, TOKEN_STRING);
    S_apply_plusses_and_negations(self, elems);
    S_discard_elems(elems, TOKEN_PLUS);
    S_discard_elems(elems, TOKEN_MINUS);
    S_discard_elems(elems, TOKEN_NOT);
    S_compose_not_queries(self, elems);
    S_winnow_boolops(self, elems);
    if (Vec_Get_Size(elems) > 2) {
        S_compose_and_queries(self, elems);
        // Don't double wrap '(a AND b)'.
        if (Vec_Get_Size(elems) == 1) { enclosed = false; }
    }
    S_discard_elems(elems, TOKEN_AND);
    if (Vec_Get_Size(elems) > 2) {
        S_compose_or_queries(self, elems);
        // Don't double wrap '(a OR b)'.
        if (Vec_Get_Size(elems) == 1) { enclosed = false; }
    }
    S_discard_elems(elems, TOKEN_OR);
    Query *retval = S_compose_subquery(self, elems, enclosed);

    return retval;
}