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); }
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); }