DIRECTORY Basics USING [CompareCard, CompareINT, Comparison], Rope USING [AppendChars, InlineSize, ROPE, 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.InlineSize[]; -- 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.InlineSize[r1]; size2: INT _ Rope.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 _ 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.InlineSize[r1]; size2: INT _ Rope.InlineSize[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 c 1985 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 Doug Wyatt, May 23, 1984 11:37:49 am PDT Michael Plass, March 1, 1985 12:06:51 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 Κξ˜codešœ™Kšœ Οmœ1™