Algorithm-MinPerfHashTwoLevel
view release on metacpan or search on metacpan
MinPerfHashTwoLevel.xs view on Meta::CPAN
struct mph_bucket *buckets= (struct mph_bucket *) ((char *)mph + mph->table_ofs);
struct mph_bucket *bucket;
U8 *state= (char *)mph + mph->state_ofs;
STRLEN key_len;
U8 *key_pv;
U64 h0;
U32 h1;
U32 h2;
U32 index;
U8 *got_key_pv;
STRLEN got_key_len;
if (SvUTF8(key_sv)) {
SV *tmp= sv_2mortal(newSVsv(key_sv));
sv_utf8_downgrade(tmp,1);
key_sv= tmp;
}
key_pv= SvPV(key_sv,key_len);
h0= mph_hash_with_state(state,key_pv,key_len);
h1= h0 >> 32;
index= h1 % mph->num_buckets;
bucket= buckets + index;
if (!bucket->xor_val)
return 0;
h2= h0 & 0xFFFFFFFF;
if ( bucket->index < 0 ) {
index = -bucket->index-1;
} else {
HASH2INDEX(index,h2,bucket->xor_val,mph->num_buckets);
}
bucket= buckets + index;
got_key_pv= strs + bucket->key_ofs;
if (bucket->key_len == key_len && memEQ(key_pv,got_key_pv,key_len)) {
if (val_sv) {
U64 gf= mph->general_flags;
sv_set_from_bucket(aTHX_ val_sv,strs,bucket->val_ofs,bucket->val_len,index,((U8*)mph)+mph->val_flags_ofs,1,
gf & MPH_VALS_ARE_SAME_UTF8NESS_MASK, MPH_VALS_ARE_SAME_UTF8NESS_SHIFT);
}
return 1;
}
return 0;
}
IV
mph_mmap(pTHX_ char *file, struct mph_obj *obj, SV *error, U32 flags) {
struct stat st;
struct mph_header *head;
int fd = open(file, O_RDONLY, 0);
void *ptr;
U32 alignment;
if (error)
sv_setpvs(error,"");
if (fd < 0) {
if (error)
sv_setpvf(error,"file '%s' could not be opened for read", file);
return MPH_MOUNT_ERROR_OPEN_FAILED;
}
if (fstat(fd,&st)==-1) {
if (error)
sv_setpvf(error,"file '%s' could not be fstat()ed", file);
return MPH_MOUNT_ERROR_FSTAT_FAILED;
}
if (st.st_size < sizeof(struct mph_header)) {
if (error)
sv_setpvf(error,"file '%s' is too small to be a valid PH2L file", file);
return MPH_MOUNT_ERROR_TOO_SMALL;
}
ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED | MPH_MAP_POPULATE, fd, 0);
close(fd); /* kernel holds its own refcount on the file, we do not need to keep it open */
if (ptr == MAP_FAILED) {
if (error)
sv_setpvf(error,"failed to create mapping to file '%s'", file);
return MPH_MOUNT_ERROR_MAP_FAILED;
}
obj->bytes= st.st_size;
obj->header= head= (struct mph_header*)ptr;
if (head->magic_num != MAGIC_DECIMAL) {
if (head->magic_num == MAGIC_BIG_ENDIAN_DECIMAL) {
if (error)
sv_setpvf(error,"this is a big-endian machine, cant handle PH2L files here");
}
if (error)
sv_setpvf(error,"file '%s' is not a PH2L file", file);
return MPH_MOUNT_ERROR_BAD_MAGIC;
}
if (head->variant < MIN_VARIANT) {
if (error)
sv_setpvf(error,"unsupported old version '%d' in '%s'", head->variant, file);
return MPH_MOUNT_ERROR_BAD_VERSION;
}
if (head->variant > MAX_VARIANT) {
if (error)
sv_setpvf(error,"unknown version '%d' in '%s'", head->variant, file);
return MPH_MOUNT_ERROR_BAD_VERSION;
}
alignment = sizeof(U64);
if (st.st_size % alignment) {
if (error)
sv_setpvf(error,"file '%s' does not have a size which is a multiple of 16 bytes", file);
return MPH_MOUNT_ERROR_BAD_SIZE;
}
if (
head->table_ofs < head->state_ofs ||
head->key_flags_ofs < head->table_ofs ||
head->val_flags_ofs < head->key_flags_ofs ||
head->str_buf_ofs < head->val_flags_ofs ||
st.st_size < head->str_buf_ofs
) {
if (error)
sv_setpvf(error,"corrupt header offsets in '%s'", file);
return MPH_MOUNT_ERROR_BAD_OFFSETS;
}
if (flags & MPH_F_VALIDATE) {
char *start= ptr;
char *state_pv= start + head->state_ofs;
char *str_buf_start= start + head->str_buf_ofs;
char *str_buf_end= start + st.st_size;
( run in 1.529 second using v1.01-cache-2.11-cpan-df04353d9ac )