DIRECTORY Basics USING [bytesPerWord], Checksum USING [ComputeChecksum], Rope, RopePrivate, RopeHash USING [PureText], RefText USING [ObtainScratch, ReleaseScratch]; RopeHashImpl: CEDAR PROGRAM IMPORTS Checksum, Rope, RopePrivate, RefText EXPORTS RopeHash SHARES Rope = BEGIN OPEN RopeHash; ROPE: TYPE = Rope.ROPE; Text: TYPE = Rope.Text; defaultSeed: CARDINAL = 31415; bytesPerWord: NAT = Basics.bytesPerWord; bufSize: NAT = 128*bytesPerWord; TextSize: NAT = SIZE[TEXT[0]]; WordAsChars: TYPE = PACKED ARRAY [0..bytesPerWord) OF CHAR; FromRefText: PUBLIC PROC [text: PureText, seed: CARDINAL] RETURNS [hash: CARDINAL] = TRUSTED { len: NAT _ text.length; nLeft: NAT = len MOD bytesPerWord; nWhole: NAT = len - nLeft; p: LONG POINTER = LOOPHOLE[text, LONG POINTER] + TextSize; hash _ seed; IF nWhole >= bytesPerWord THEN { hash _ Checksum.ComputeChecksum[hash, nWhole/bytesPerWord, p]; }; IF nLeft # 0 THEN TRUSTED { leftovers: WordAsChars _ ALL[0C]; FOR j: NAT IN [0..nLeft) DO leftovers[j] _ Rope.QFetch[LOOPHOLE[text], nWhole+j]; ENDLOOP; hash _ Checksum.ComputeChecksum[hash, SIZE[WordAsChars], @leftovers]; }; }; FromRope: PUBLIC PROC [rope: ROPE, case: BOOL, start: INT, len: INT, seed: CARDINAL] RETURNS [hash: CARDINAL] = TRUSTED { rem: INT _ RopePrivate.NonNeg[Rope.InlineLength[rope] - RopePrivate.NonNeg[start]]; IF rem < len THEN len _ rem; IF case AND start = 0 AND rem = len THEN WITH rope SELECT FROM text: Text => RETURN[FromRefText[LOOPHOLE[text], seed]]; ENDCASE; { buf: REF TEXT _ RefText.ObtainScratch[bufSize]; p: LONG POINTER = LOOPHOLE[buf, LONG POINTER] + SIZE[TEXT[0]]; bytes: NAT _ 0; hash _ seed; WHILE rem > 0 DO buf.length _ 0; bytes _ Rope.AppendChars[buf, rope, start, rem]; IF NOT case THEN FOR i: NAT IN [0..bytes) DO c: CHAR = Rope.QFetch[LOOPHOLE[buf], i]; IF c <= 'Z AND c >= 'A THEN RopePrivate.QStore[c + ('a-'A), LOOPHOLE[buf], i]; ENDLOOP; hash _ FromRefText[buf, hash]; start _ start + bytes; rem _ rem - bytes; ENDLOOP; RefText.ReleaseScratch[buf]; RETURN [hash]; }; }; END. ~RopeHashImpl.mesa Copyright (C) 1984, 1985 Xerox Corporation. All rights reserved. Michael Plass, January 18, 1985 12:48:44 pm PST Russ Atkinson (RRA) May 15, 1985 2:38:58 pm PDT Limit len to be at worst the remainder of the string If case does not matter, and we have a flat rope, and the whole rope is to be hashed, then we have the fast case. In the hard case we have to move the bytes from the rope into a buffer, adjust the buffer for lower case, then perform the checksum on the buffer. We keep doing this until there are no more chars to be moved. Make the buffer lower case. We avoid bounds checking to speed things up. Κ¦˜code™K™AK™/K™/—K˜šΟk ˜ Kšœœ˜Kšœ œ˜!Kšœ˜Kšœ ˜ Kšœ œ ˜Kšœœ!˜.K˜—šœ ˜Kšœ%˜,Kšœ ˜Kšœ˜ šœœœ ˜K˜—Kšœœœ˜Kšœœ ˜Kšœ œ ˜Kšœœ˜(Kšœ œ˜ K˜Kšœ œœœ˜š œ œœœœœ˜;K˜—šΟn œœœœœœœ˜^Kšœœ˜Kšœœœ˜"Kšœœ˜Kš œœœœœœ ˜:Kšœ ˜ šœœ˜ Kšœ>˜>K˜—šœ œœ˜Kšœœ˜!šœœœ ˜Kšœœ˜5Kšœ˜—Kšœ&œ˜EK˜—Kšœ˜K˜—šžœœœœœ œœœœœœ˜yKšœœK˜Sšœ œ ˜Kšœ4™4—š œœ œ œœœ˜>šœ˜Kšœq™qKšœ œ˜*—Kšœ˜—šœ˜KšœΡ™ΡKšœœœ"˜/Kšœœœœœœœœ˜>Kšœœ˜Kšœ ˜ šœ ˜Kšœ˜Kšœ0˜0šœœ˜KšœI™Išœœœ ˜Kšœœœ ˜(Kšœ œ œ!œ ˜NKšœ˜——Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—Kšœ˜K˜—Kšœ˜K˜——…—κ