ref: fa9f4c5c6852ce467644f610e77504664cb86af4
dir: /appl/lib/attrhash.b/
implement Attrhash, Attrindex;
include "sys.m";
sys: Sys;
include "bufio.m";
bufio: Bufio;
include "attrdb.m";
init(): string
{
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
if(bufio == nil)
return sys->sprint("can't load %s: %r", Bufio->PATH);
return nil;
}
attrindex(): Attrindex
{
return load Attrindex "$self";
}
Index.open(dbf: Attrdb->Dbf, attr: string, fd: ref Sys->FD): ref Index
{
(ok, d) := sys->fstat(fd);
if(ok < 0 || dbf.dir == nil || dbf.dir.mtime > d.mtime)
return nil;
length := int d.length;
if(length < NDBHLEN)
return nil;
buf := array[length] of byte;
if(sys->read(fd, buf, len buf) != len buf)
return nil;
mtime := get4(buf);
if(mtime != dbf.dir.mtime)
return nil;
size := get3(buf[4:]);
return ref Index(fd, attr, d.mtime, size, buf[8:]);
}
#Index.firstoff(ind: self ref Index, val: string): ref Attrdb->Dbptr
#{
# o := hash(val, ind.size)*NDBPLEN;
# p := get3(tab[o:]);
# if(p == NDBNAP)
# return nil;
# if((p & NDBCHAIN) == 0)
# return ref Attrdb.Direct(p);
# p &= ~NDBCHAIN;
# return ref Attrdb.Hash(get3(tab[p:]), get3(tab[p+NDBPLEN:]));
#}
#Index.nextoff(ind: self ref Index, val: string, ptr: ref Attrdb->Dbptr): (int, ref Attrdb->Dbptr)
#{
# pick p := ptr {
# Hash =>
# o := get3(tab[p.current:]);
# if((o & NDBCHAIN) == 0)
# return (o, ref Attrdb.Direct(p.next));
# o &= ~NDBCHAIN;
# o1 := get3(tab[o:]);
# o2 := get3(tab[o+NDBPLEN:]);
#
# o := hash(val, ind.size)*NDBPLEN;
# p := get3(tab[o:]);
# if(p == NDBNAP)
# return nil;
# for(; (p := get3(tab[o:])) != NDBNAP; o = p & ~NDBCHAIN)
# if((p & NDBCHAIN) == 0){
# put3(tab[o:], chain | NDBCHAIN);
# put3(tab[chain:], p);
# put3(tab[chain+NDBPLEN:], offset);
# return chain+2*NDBPLEN;
# }
# return nil;
#}
#
# this must be the same hash function used by Plan 9's ndb
#
hash(s: string, hlen: int): int
{
h := 0;
for(i := 0; i < len s; i++)
if(s[i] >= 16r80){
# could optimise by calculating utf ourselves
a := array of byte s;
for(i=0; i<len a; i++)
h = (h*13) + int a[i] - 'a';
break;
}else
h = (h*13) + s[i]-'a';
if(h < 0)
return int((big h & big 16rFFFFFFFF)%big hlen);
return h%hlen;
}
get3(a: array of byte): int
{
return (int a[2]<<16) | (int a[1]<<8) | int a[0];
}
get4(a: array of byte): int
{
return (int a[3]<<24) | (int a[2]<<16) | (int a[1]<<8) | int a[0];
}