<> <> <> DIRECTORY Basics USING [bytesPerWord], Checksum USING [ComputeChecksum], TypeStrings USING [TypeString], TypeHash USING [TypeKey, nullKey]; TypeHashImpl: MONITOR IMPORTS Checksum EXPORTS TypeHash = BEGIN OPEN TypeStrings; TypeKey: TYPE = TypeHash.TypeKey; nullKey: TypeKey = TypeHash.nullKey; KeyPtr: TYPE = LONG POINTER TO TypeKey; KeyAsChars: TYPE = PACKED ARRAY [0 .. CharsPerKey) OF CHAR; WordsPerKey: CARDINAL = SIZE[TypeKey]; CharsPerKey: CARDINAL = Basics.bytesPerWord*WordsPerKey; KeyAsCharsPtr: TYPE = LONG POINTER TO KeyAsChars; DoubleKey: TYPE = RECORD [key1: TypeKey, key2: TypeKey]; EndBytes: TYPE = PACKED ARRAY [0..Basics.bytesPerWord) OF CHAR; EndBytesPtr: TYPE = LONG POINTER TO EndBytes; TypeStrHash: PUBLIC PROC [ts: TypeString] RETURNS [key: TypeKey _ nullKey] = { <> chars: CARDINAL _ ts.length; ptr: LONG POINTER TO CARDINAL _ LOOPHOLE[ts+SIZE[StringBody]]; double: DoubleKey _ [nullKey, nullKey]; pos: CARDINAL _ 0; double.key1[0] _ chars+1; WHILE chars >= Basics.bytesPerWord DO mod: [0..WordsPerKey) _ pos MOD WordsPerKey; double.key2[mod] _ (ptr+pos)^; pos _ pos + SIZE[CARDINAL]; double.key1[mod] _ Checksum.ComputeChecksum[pos, WordsPerKey+1, @double.key1[mod]]; chars _ chars - Basics.bytesPerWord; ENDLOOP; IF chars # 0 THEN { endBytesPtr: EndBytesPtr _ LOOPHOLE[ptr+pos]; endBytes: EndBytes _ ALL[0C]; mod: [0..WordsPerKey) _ pos MOD WordsPerKey; FOR i: NAT IN [0..chars) DO endBytes[i] _ endBytesPtr[i]; ENDLOOP; double.key2[mod] _ LOOPHOLE[endBytes]; double.key1[mod] _ Checksum.ComputeChecksum[pos+1, WordsPerKey+1, @double+(pos MOD WordsPerKey)]; }; key _ double.key1; IF key[0] = 0 AND key[1] = 0 AND key[2] = 0 AND key[3] = 0 THEN { <> key[0] _ chars+1; }; }; END.