DIRECTORY Basics USING [CompareCard, CompareInt, Comparison], Rope USING [AppendChars, ROPE, Size, Text], RopeReader USING [Body, Get, GetIndex, GetRope, MaxLen, Mode, ReadChar, Ref, SetPosition]; RopeReaderImpl: CEDAR MONITOR IMPORTS Basics, Rope, RopeReader EXPORTS RopeReader = BEGIN OPEN RopeReader; ROPE: TYPE = Rope.ROPE; Text: TYPE = Rope.Text; ReadOffEnd: PUBLIC ERROR = CODE; ReadChar: PUBLIC PROC [reader: Ref, mode: Mode] RETURNS [char: CHAR] = { rope: ROPE ~ reader.rope; -- the rope being read size: INT ~ rope.Size[]; -- size of the rope index: INT ~ reader.index+reader.current; -- index of next char that Get would read text: REF TEXT ~ reader.text; -- text buffer length: NAT ¬ text.maxLength; -- number of chars to be read into buffer forward: BOOL ~ SELECT mode FROM get, peek => TRUE, backwards, peekbackwards => FALSE, ENDCASE => ERROR; inBounds: BOOL ~ IF forward THEN index IN[0..size) ELSE index IN(0..size]; IF NOT inBounds THEN { IF reader.charForEndOfRope THEN RETURN[reader.endChar] ELSE ERROR ReadOffEnd; }; IF forward THEN { rem: INT ~ size-index; IF rem { reader.current ¬ i+1; RETURN[text[i]] }; backwards => { RETURN[text[reader.current ¬ i-1]] }; peek => { RETURN[text[i]] }; peekbackwards => { RETURN[text[i-1]] }; ENDCASE => ERROR; } ELSE ERROR; }; EqSubstrs: PUBLIC PROC [r1, r2: ROPE, start1, start2, len: INT, rdr1, rdr2: Ref ¬ NIL] RETURNS [eq: BOOL] = { free1, free2: BOOL ¬ FALSE; size1: INT ¬ Rope.Size[r1]; size2: INT ¬ Rope.Size[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 ¬ NAT.LAST; -- loop on NAT instead of INT IF len NULL; ENDLOOP; IF free1 THEN FreeRopeReader[rdr1]; IF free2 THEN FreeRopeReader[rdr2]; }; CompareSubstrs: PUBLIC PROC [r1, r2: ROPE, start1, len1, start2, len2: INT, rdr1, rdr2: Ref ¬ NIL, case: BOOL ¬ TRUE] RETURNS [result: Basics.Comparison] = { size1: INT ¬ Rope.Size[r1]; size2: INT ¬ Rope.Size[r2]; rem, rem1, rem2: INT; free1, free2: BOOL ¬ 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 ¬ NAT.LAST; IF rem NULL; ENDLOOP; IF free1 THEN FreeRopeReader[rdr1]; IF free2 THEN FreeRopeReader[rdr2]; IF result # equal THEN RETURN; -- if a character differerence, then return it RETURN [Basics.CompareInt[len1, len2]]; -- if equal so far, the length determines }; defaultSize: NAT ¬ 200; roperdr1: Ref ¬ NIL; roperdr2: Ref ¬ NIL; roperdr3: Ref ¬ NIL; SetDefaultSize: PUBLIC ENTRY PROC [size: NAT] = { defaultSize ¬ size; roperdr1 ¬ roperdr2 ¬ roperdr3 ¬ NIL; }; Create: PUBLIC PROC [size: NAT ¬ 0] RETURNS [Ref] = { IF size=0 THEN size ¬ defaultSize; RETURN[NEW[Body ¬ [text: NEW[TEXT[size]]]]]; }; GetRopeReader: PUBLIC ENTRY PROC RETURNS [reader: Ref] = { SELECT Ref.NIL FROM # roperdr3 => { reader ¬ roperdr3; roperdr3 ¬ NIL }; # roperdr2 => { reader ¬ roperdr2; roperdr2 ¬ NIL }; # roperdr1 => { reader ¬ roperdr1; roperdr1 ¬ NIL }; ENDCASE => reader ¬ Create[]; }; FreeRopeReader: PUBLIC ENTRY PROC [reader: Ref] = { SetPosition[reader, NIL]; IF reader.text.maxLength#defaultSize THEN RETURN; reader.charForEndOfRope ¬ FALSE; IF roperdr3 = reader OR roperdr2 = reader OR roperdr1 = reader THEN ERROR; SELECT Ref.NIL FROM roperdr3 => roperdr3 ¬ reader; roperdr2 => roperdr2 ¬ reader; roperdr1 => roperdr1 ¬ reader; ENDCASE => NULL; }; END. θ RopeReaderImpl.mesa Copyright Σ 1985, 1986, 1988, 1991 by Xerox Corporation. All rights reserved. written by Bill Paxton, January 1981 Bill Paxton, December 22, 1981 10:24 am Maxwell, January 5, 1983 12:05 pm Russ Atkinson, March 13, 1985 9:14:18 pm PST Paul Rovner, August 10, 1983 4:21 pm Michael Plass, September 24, 1991 11:55 am PDT Doug Wyatt, November 4, 1988 4:38:19 pm PST 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 special crock by RRA, verified as generating good code (generates few jumps) ***** rope reader cache Κ–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœC™NKšœ%™%Kšœ'™'Kšœ!™!Kšœ,™,Kšœ$™$Kšœ.™.Kšœ+™+K™—šΟk ˜ Kšœžœ(˜4Kšœžœžœ˜,Kšœ žœJ˜Z—K˜šΟnœžœž˜Kšžœ˜ Kšžœ ˜Kšœžœžœ ˜K˜Kšžœžœžœ˜Kšœžœ ˜Kšœ žœžœžœ˜ K˜—š Ÿœžœžœžœžœ˜HKšœžœΟc˜0Kšœžœ ˜,Kšœžœ  )˜SKšœžœžœ ˜,Kšœžœ )˜Gšœ žœžœž˜ Kš œ žœžœžœžœ˜G—Kš œ žœžœ žœžœ žœžœ ˜Jšžœžœ žœ˜Kšžœžœžœ˜6Kšžœžœ ˜K˜—šžœ˜ šžœ˜Kšœžœ˜Kšžœ žœ˜ K˜)K˜—šžœ˜Kšžœžœ˜$K˜5K˜——K˜K˜Ršžœžœ˜Kšœžœ˜šžœž˜Kšœžœ ˜1Kšœžœ˜4Kšœ žœ ˜Kšœžœ˜'Kšžœžœ˜—K˜—Kšžœžœ˜ K˜K˜—šŸ œžœžœ žœžœžœžœžœ˜mKšœG™GKšœ?™?Kšœžœžœ˜Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœ žœ˜š žœ žœžœ%žœžœžœ˜QKš žœžœžœžœžœ˜.Kš žœžœžœžœžœ˜/—Kšžœžœžœ#žœ˜