Пример #1
0
void
LexIndex_seek(LexIndex *self, Obj *target)
{
    FieldType   *type   = self->field_type;
    i32_t        lo     = 0;
    i32_t        hi     = self->size - 1;
    i32_t        result = -100;

    if (target == NULL || self->size == 0) { 
        self->tick = 0;
        return;
    }
    else {
        if ( !OBJ_IS_A(target, CHARBUF)) {
            THROW("Target is a %o, and not comparable to a %o",
                Obj_Get_Class_Name(target), CHARBUF.name);
        }
        /* TODO: 
        Obj *first_obj = VA_Fetch(terms, 0);
        if ( !Obj_Is_A(target, Obj_Get_VTable(first_obj)) ) {
            THROW("Target is a %o, and not comparable to a %o",
                Obj_Get_Class_Name(target), Obj_Get_Class_Name(first_obj));
        }
        */
    }

    /* Divide and conquer. */
    while (hi >= lo) {
        const i32_t mid = lo + ((hi - lo) / 2);
        const i64_t offset 
            = (i64_t)Math_decode_bigend_u64(self->offsets + mid);
        char *data = self->data + offset;
        size_t size = Math_decode_c32(&data);
        i64_t comparison;

        ViewCB_Assign_Str(self->term, data, size);
        comparison = FType_Compare_Values(type, target, (Obj*)self->term);
        if (comparison < 0) {
            hi = mid - 1;
        }
        else if (comparison > 0) {
            lo = mid + 1;
        }
        else {
            result = mid;
            break;
        }
    }

    /* Record the index of the entry we've seeked to, then read entry. */
    self->tick = hi == -1   ? 0  /* indicating that target lt first entry */
           : result == -100 ? hi /* if result is still -100, it wasn't set */
           : result;
    S_read_entry(self);
}
Пример #2
0
void
LexIndex_Seek_IMP(LexIndex *self, Obj *target) {
    LexIndexIVARS *const ivars = LexIndex_IVARS(self);
    TermStepper *term_stepper = ivars->term_stepper;
    InStream    *ix_in        = ivars->ix_in;
    FieldType   *type         = ivars->field_type;
    int32_t      lo           = 0;
    int32_t      hi           = ivars->size - 1;
    int32_t      result       = -100;

    if (target == NULL || ivars->size == 0) {
        ivars->tick = 0;
        return;
    }
    else {
        if (!Obj_is_a(target, STRING)) {
            THROW(ERR, "Target is a %o, and not comparable to a %o",
                  Obj_get_class_name(target), Class_Get_Name(STRING));
        }
        /* TODO:
        Obj *first_obj = Vec_Fetch(terms, 0);
        if (!Obj_is_a(target, Obj_get_class(first_obj))) {
            THROW(ERR, "Target is a %o, and not comparable to a %o",
                Obj_get_class_name(target), Obj_get_class_name(first_obj));
        }
        */
    }

    // Divide and conquer.
    while (hi >= lo) {
        const int32_t mid = lo + ((hi - lo) / 2);
        const int64_t offset
            = (int64_t)NumUtil_decode_bigend_u64(ivars->offsets + mid);
        InStream_Seek(ix_in, offset);
        TermStepper_Read_Key_Frame(term_stepper, ix_in);

        // Compare values.  There is no need for a NULL-check because the term
        // number is alway between 0 and ivars->size - 1.
        Obj *value = TermStepper_Get_Value(term_stepper);
        int32_t comparison = FType_Compare_Values(type, target, value);

        if (comparison < 0) {
            hi = mid - 1;
        }
        else if (comparison > 0) {
            lo = mid + 1;
        }
        else {
            result = mid;
            break;
        }
    }

    // Record the index of the entry we've seeked to, then read entry.
    ivars->tick = hi == -1 // indicating that target lt first entry
                 ? 0
                 : result == -100 // if result is still -100, it wasn't set
                 ? hi
                 : result;
    S_read_entry(self);
}