DIRECTORY RopeReader, RopeFrom, Rope, RopeInline, Environment, Space; RopeReaderMiscImpl: CEDAR MONITOR IMPORTS RopeReader, Rope, RopeInline, RopeFrom, Space --, RTTypesBasic, Process EXPORTS RopeReader SHARES RopeReader, Rope = BEGIN OPEN RopeReader, RopeInline; EqSubstrs: PUBLIC PROC [r1,r2: ROPE, start1,start2,len: Offset, rdr1,rdr2: Ref _ NIL] RETURNS [eq: BOOLEAN] = { free1, free2: BOOLEAN _ FALSE; size1: Offset _ InlineSize[r1]; size2: Offset _ InlineSize[r2]; start1 _ MIN[start1,size1]; start2 _ MIN[start2,size2]; IF len=MaxLen THEN { IF (len _ size1-start1) # size2-start2 THEN RETURN [FALSE] } ELSE IF start1+len > size1 THEN RETURN [FALSE] ELSE IF start2+len > size2 THEN RETURN [FALSE]; IF rdr1 = NIL THEN { rdr1 _ GetRopeReader[]; free1 _ TRUE }; IF rdr2 = NIL THEN { rdr2 _ GetRopeReader[]; free2 _ TRUE }; SetPosition[rdr1,r1,start1]; SetPosition[rdr2,r2,start2]; eq _ TRUE; WHILE len > 0 DO num: NAT _ Short[MIN[len,LAST[NAT]]]; -- loop on NAT instead of Offset len _ len-num; THROUGH [0..num) DO IF Get[rdr1]#Get[rdr2] THEN { eq _ FALSE; GOTO Finis }; ENDLOOP; REPEAT Finis => NULL; ENDLOOP; IF free1 THEN FreeRopeReader[rdr1]; IF free2 THEN FreeRopeReader[rdr2] }; CompareSubstrs: PUBLIC PROC [ r1, r2: ROPE, start1, len1, start2, len2: Offset, rdr1, rdr2: Ref _ NIL, case: BOOLEAN _ TRUE] RETURNS [result: Environment.Comparison] = { Lower: PROC [c: CHARACTER] RETURNS [CHARACTER] = INLINE { RETURN [IF c NOT IN ['A..'Z] THEN c ELSE LOOPHOLE[LOOPHOLE[c,CARDINAL]+40B,CHARACTER]] }; size1: Offset _ InlineSize[r1]; size2: Offset _ InlineSize[r2]; rem, rem1, rem2: Offset; free1, free2: BOOLEAN _ FALSE; rem1 _ IF start1 > size1 THEN 0 ELSE size1-start1; rem2 _ IF start2 > size2 THEN 0 ELSE size2-start2; IF rdr1 = NIL THEN { rdr1 _ GetRopeReader[]; free1 _ TRUE }; IF rdr2 = NIL THEN { rdr2 _ GetRopeReader[]; free2 _ TRUE }; len1 _ MIN[len1,rem1]; len2 _ MIN[len2,rem2]; rem _ MIN[len1,len2]; SetPosition[rdr1,r1,start1]; SetPosition[rdr2,r2,start2]; result _ equal; WHILE rem > 0 DO num: NAT _ Short[MIN[rem,LAST[NAT]]]; rem _ rem-num; THROUGH [0..num) DO c1: CHARACTER _ Get[rdr1]; c2: CHARACTER _ Get[rdr2]; IF ~case THEN { c1 _ Lower[c1]; c2 _ Lower[c2] }; SELECT c1 FROM < c2 => { result _ less; GOTO Finis }; > c2 => { result _ greater; GOTO Finis }; ENDCASE; ENDLOOP; REPEAT Finis => NULL; ENDLOOP; IF free1 THEN FreeRopeReader[rdr1]; IF free2 THEN FreeRopeReader[rdr2]; RETURN [ IF result # equal THEN result ELSE SELECT TRUE FROM len1 < len2 => less, len1 > len2 => greater, ENDCASE => equal] }; numCharsArrays: INT _ 0; -- number allocated CharsRope: PUBLIC ENTRY PROC [ chars: Chars, space: Space.Handle _ Space.nullHandle] RETURNS [ROPE] = TRUSTED { ENABLE UNWIND => NULL; RETURN [RopeFrom.qZone.NEW[Tobject _ [node[object[ charsPerArray,LOOPHOLE[chars],CharsFetch,CharsMap,NIL]]]]] }; spacesFinalized: INT _ 0; charsFinalized: INT _ 0; countCList: INT _ 0; -- set by calling CountCList CharsFetch: SAFE PROC [data: REF, index: Offset] RETURNS [c:CHAR] = TRUSTED { WITH data SELECT FROM x: Chars => RETURN[x[Short[index]]]; ENDCASE => ERROR Rope.NoRope }; CharsMap: SAFE PROC [base: REF, start,len: Offset, action: PROC [CHAR] RETURNS [BOOLEAN]] RETURNS [BOOLEAN] = TRUSTED { WITH base SELECT FROM x: Chars => { st: NAT _ Short[start]; FOR i: NAT IN [st..st+Short[len]) DO IF action[x[i]] THEN RETURN [TRUE]; ENDLOOP }; ENDCASE => ERROR Rope.NoRope; RETURN [FALSE] }; Create: PUBLIC PROC RETURNS [Ref] = { RETURN[RopeFrom.qZone.NEW[Body]] }; roperdr1, roperdr2, roperdr3: Ref; -- shared rope readers GetRopeReader: PUBLIC ENTRY PROC RETURNS [reader: Ref] = { IF roperdr3 # NIL THEN { reader _ roperdr3; roperdr3 _ NIL } ELSE IF roperdr2 # NIL THEN { reader _ roperdr2; roperdr2 _ NIL } ELSE IF roperdr1 # NIL THEN { reader _ roperdr1; roperdr1 _ NIL } ELSE reader _ Create[] }; FreeRopeReader: PUBLIC ENTRY PROC [reader: Ref] = { SetPosition[reader, NIL]; reader.charForEndOfRope _ FALSE; IF roperdr3 = reader OR roperdr2 = reader OR roperdr1 = reader THEN ERROR; IF roperdr3 = NIL THEN roperdr3 _ reader ELSE IF roperdr2 = NIL THEN roperdr2 _ reader ELSE IF roperdr1 = NIL THEN roperdr1 _ reader }; StartRopeReaderMisc: PUBLIC PROC = TRUSTED { }; END. ÌRopeReaderMiscImpl.mesa written by Bill Paxton, January 1981 last edit by Paxton, February 7, 1983 9:34 am last edit by McGregor, June 10, 1982 3:18 pm Last Edited by: Maxwell, January 5, 1983 12:07 pm Last Edited by: Plass, March 7, 1983 2:27 pm -- uses readers rdr1 and rdr2 to read ropes r1 and r2 to test for equality -- returns TRUE if r1 is same as len chars of r2 starting at start -- uses readers rdr1 and rdr2 to compare ropes r1 and r2 -- if ~case then all characters forced lowercase for comparison -- implementation of ropes using character arrays CList: TYPE = REF CListBody; CListBody: TYPE = RECORD [chars: Chars, space: Space.Handle, next: CList]; charsList: CList _ NIL; FOR lst:CList _ charsList, lst.next UNTIL lst=NIL DO IF lst.chars = chars THEN { IF lst.space = Space.nullHandle THEN lst.space _ space ELSE IF space # Space.nullHandle THEN ERROR; EXIT }; REPEAT FINISHED => { charsList _ RopeFrom.qZone.NEW[CListBody _ [chars,space,charsList]]; numCharsArrays _ numCharsArrays+1 }; ENDLOOP; CharsFinalizer: PROC [charsFQ: RTTypesBasic.FinalizationQueue] = TRUSTED { DO chars: REF CharsArray = NARROW[RTTypesBasic.FQNext[charsFQ]]; space: Space.Handle = RemoveFromCList[chars]; IF space # Space.nullHandle THEN { spacesFinalized _ spacesFinalized+1; Space.Unmap[space]; Space.Map[space, Space.defaultWindow] }; ENDLOOP }; RemoveFromCList: ENTRY PROC [chars: Chars] RETURNS [space: Space.Handle] = { ENABLE UNWIND => NULL; lst, prev: CList; charsFinalized _ charsFinalized+1; IF (lst_charsList)=NIL THEN RETURN [Space.nullHandle]; IF lst.chars = chars THEN { lst.chars _ NIL; charsList _ lst.next; lst.next _ NIL; RETURN [lst.space] }; DO prev _ lst; IF (lst _ lst.next)=NIL THEN RETURN [Space.nullHandle]; IF lst.chars = chars THEN { lst.chars _ NIL; prev.next _ lst.next; lst.next _ NIL; RETURN [lst.space] }; ENDLOOP }; CountCList: ENTRY PROC = { ENABLE UNWIND => NULL; countCList_ 0; FOR lst:CList _ charsList, lst.next UNTIL lst=NIL DO countCList _ countCList+1; ENDLOOP }; -- ***** rope reader cache -- ***** Initialization charsFQ: RTTypesBasic.FinalizationQueue = RTTypesBasic.NewFQ[]; -- for CharsArrays RTTypesBasic.EstablishFinalization[CODE[CharsArray],1,charsFQ]; Process.Detach[FORK CharsFinalizer[charsFQ]] Ê ˜JšÏc™Jš%™%Jš-™-Jš,™,J™1J™,šÏk ˜ J˜ J˜ J˜J˜ Jšœ ˜ J˜J˜—šœž ˜!Jšžœ/˜OJšžœ ˜Jšžœ˜J˜—Jšžœžœ˜"J˜š Ïn œžœžœ žœ.žœ˜UJšžœžœ˜JšJ™JJšB™BJšœžœžœ˜J˜J˜Jšœ žœ˜Jšœ žœ˜Jš žœ žœžœ%žœžœžœ˜QJš žœžœžœžœžœ˜.Jš žœžœžœžœžœ˜/Jšžœžœžœ#žœ˜