static void test_bigend_u64(TestBatch *batch) { size_t count = 32; uint64_t *ints = TestUtils_random_u64s(NULL, count, 0, U64_MAX); size_t amount = (count + 1) * sizeof(uint64_t); char *allocated = (char*)CALLOCATE(amount, sizeof(char)); char *encoded = allocated + 1; // Intentionally misaligned. char *target = encoded; for (size_t i = 0; i < count; i++) { NumUtil_encode_bigend_u64(ints[i], &target); target += sizeof(uint64_t); } target = encoded; for (size_t i = 0; i < count; i++) { uint64_t got = NumUtil_decode_bigend_u64(target); TEST_TRUE(batch, got == ints[i], "bigend u64"); target += sizeof(uint64_t); } target = encoded; NumUtil_encode_bigend_u64(1, &target); TEST_INT_EQ(batch, encoded[0], 0, "Truly big-endian"); TEST_INT_EQ(batch, encoded[7], 1, "Truly big-endian"); FREEMEM(allocated); FREEMEM(ints); }
double InStream_read_f64(InStream *self) { union { double d; uint64_t u64; } duo; SI_read_bytes(self, (char*)&duo, sizeof(double)); #ifdef LITTLE_END duo.u64 = NumUtil_decode_bigend_u64(&duo.u64); #endif return duo.d; }
static INLINE uint64_t SI_read_u64(InStream *self) { uint64_t retval; SI_read_bytes(self, (char*)&retval, 8); #ifdef LITTLE_END retval = NumUtil_decode_bigend_u64((char*)&retval); #endif return retval; }
static void S_read_entry(LexIndex *self) { LexIndexIVARS *const ivars = LexIndex_IVARS(self); InStream *ix_in = ivars->ix_in; TermInfo *const tinfo = ivars->tinfo; int64_t offset = (int64_t)NumUtil_decode_bigend_u64(ivars->offsets + ivars->tick); InStream_Seek(ix_in, offset); TermStepper_Read_Key_Frame(ivars->term_stepper, ix_in); int32_t doc_freq = InStream_Read_C32(ix_in); TInfo_Set_Doc_Freq(tinfo, doc_freq); TInfo_Set_Post_FilePos(tinfo, InStream_Read_C64(ix_in)); int64_t skip_filepos = doc_freq >= ivars->skip_interval ? InStream_Read_C64(ix_in) : 0; TInfo_Set_Skip_FilePos(tinfo, skip_filepos); TInfo_Set_Lex_FilePos(tinfo, InStream_Read_C64(ix_in)); }
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); }