DIRECTORY Basics USING [Comparison], Rope USING [MaxLen, ROPE]; RopeReader: CEDAR DEFINITIONS ~ BEGIN ROPE: TYPE ~ Rope.ROPE; MaxLen: INT ~ Rope.MaxLen; Ref: TYPE ~ REF Body; Body: TYPE ~ PRIVATE RECORD [ text: REF TEXT _, -- text buffer (must not be NIL) current: NAT _ 0, -- index in text of current character (next to be returned by Get) rope: ROPE _ NIL, -- rope that we are reading index: INT _ 0, -- index in rope of text[0] charForEndOfRope: BOOLEAN _ FALSE, endChar: CHAR _ 0C -- char to return when reach end of rope ]; ReadOffEnd: ERROR; Create: PROC[size: NAT _ 0] RETURNS [Ref]; GetRope: PROC [reader: Ref] RETURNS [rope: ROPE] ~ INLINE { RETURN [reader.rope] }; GetIndex: PROC [reader: Ref] RETURNS [index: INT] ~ INLINE { RETURN [reader.index+reader.current] }; Position: PROC [reader: Ref] RETURNS [rope: ROPE, index: INT] ~ INLINE { RETURN [rope: GetRope[reader], index: GetIndex[reader]] }; SetPosition: PROC [reader: Ref, rope: ROPE, index: INT _ 0] ~ INLINE { IF GetRope[reader]=rope AND GetIndex[reader]=index THEN RETURN; reader.rope _ rope; reader.current _ 0; reader.text.length _ 0; reader.index _ index; }; SetIndex: PROC [reader: Ref, index: INT _ 0] ~ INLINE { IF reader.index+reader.current # index THEN {reader.current _ 0; reader.text.length _ 0; reader.index _ index} }; BackupIndex: PROC [reader: Ref, amount: INT] ~ INLINE { SetIndex[reader, GetIndex[reader]-amount] }; BumpIndex: PROC [reader: Ref, amount: INT] ~ INLINE { SetIndex[reader, GetIndex[reader]+amount] }; GetEndChar: PROC [reader: Ref] RETURNS [endChar: CHAR] ~ INLINE { RETURN [reader.endChar] }; CharForEndOfRope: PROC [reader: Ref] RETURNS [BOOLEAN] ~ INLINE { RETURN [reader.charForEndOfRope] }; SetCharForEndOfRope: PROC [reader: Ref, char: CHAR] ~ INLINE { reader.endChar _ char; reader.charForEndOfRope _ TRUE }; ClearCharForEndOfRope: PROC [reader: Ref] ~ INLINE { reader.charForEndOfRope _ FALSE }; Mode: PRIVATE TYPE ~ {get, backwards, peek, peekbackwards}; ReadChar: PRIVATE PROC [reader: Ref, mode: Mode] RETURNS [CHAR]; Get: PROC [reader: Ref] RETURNS [CHAR] ~ INLINE { text: REF TEXT ~ reader.text; i: NAT ~ reader.current; IF i0 THEN RETURN[reader.text[reader.current _ i-1]] ELSE RETURN[ReadChar[reader, $backwards]] }; Peek: PROC [reader: Ref] RETURNS [CHAR] ~ INLINE { text: REF TEXT ~ reader.text; i: NAT ~ reader.current; IF i0 THEN RETURN[reader.text[i-1]] ELSE RETURN[ReadChar[reader, $peekbackwards]] }; Equal: PROC [r1, r2: ROPE, rdr1, rdr2: Ref _ NIL] RETURNS [BOOLEAN] ~ INLINE { RETURN [EqSubstrs[r1, r2, 0, 0, MaxLen, rdr1, rdr2]] }; EqSubstrs: PROC [r1, r2: ROPE, start1, start2, len: INT, rdr1, rdr2: Ref _ NIL] RETURNS [BOOL]; Compare: PROC [r1,r2: ROPE, rdr1,rdr2: Ref _ NIL, case: BOOLEAN _ TRUE] RETURNS [Basics.Comparison] ~ INLINE {RETURN [CompareSubstrs[r1,r2,0,MaxLen,0,MaxLen,rdr1,rdr2,case]] }; CompareSubstrs: PROC [r1, r2: ROPE, start1, len1, start2, len2: INT, rdr1, rdr2: Ref _ NIL, case: BOOL _ TRUE] RETURNS [Basics.Comparison]; GetRopeReader: PROC RETURNS [reader: Ref]; FreeRopeReader: PROC [reader: Ref]; SetDefaultSize: PROC[size: NAT]; END. ςRopeReader.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. written by Bill Paxton, January 1981 last edit by Paxton, September 13, 1982 9:33 am last edit by McGregor, June 10, 1982 2:30 pm last edit by Maxwell, January 5, 1983 8:36 am last edit by Russ Atkinson, July 22, 1983 9:33 am last edit by Doug Wyatt, January 19, 1984 10:04:50 am PST Plass, March 1, 1985 11:47:10 am PST RopeReader provides fast inline access to characters in ropes designed for speed in reading a sequence of characters, either forwards or backwards Overview create a reader by RopeReader.Create reader: RopeReader.Ref _ RopeReader.Create[]; position it where you want to read by SetPosition RopeReader.SetPosition[reader,rope,index]; where rope is to the one to read from, and index is the initial position for the reader you can reposition a reader at any time read its position in any of the following ways: [rope,index] _ RopeReader.Position[reader]; rope _ RopeReader.GetRope[reader]; index _ RopeReader.GetIndex[reader]; to read in ascending order (left to right) initialize position at index of first character to be read for example, use 0 to start at beginning of rope then call Get which reads to the right and increments the position char _ RopeReader.Get[reader]; to read in descending order (right to left) initialize position after first character to be read for example, use size of rope to start at end then call Backwards which reads to the left and decrements the position char _ RopeReader.Backwards[reader]; can also get a character without changing the reader position to look at the next character that Get would return, call Peek char _ RopeReader.Peek[reader]; to look at what Backwards would return, call PeekBackwards char _ RopeReader.PeekBackwards[reader]; can intermix reading or peeking to left and right don't need to reinitialize the reader to change direction if read off either end of rope, you can choose either to get an error or a client-specified character there are equality and comparison routines that use readers for efficiency Equal, EqSubstr, EqSubstrs Compare, CompareSubstr, CompareSubstrs operations are also provided to read a block of characters destination given by either a REF TEXT or a REF chars array can read either forward or backwards from source Declarations if true, return endChar; else give ERROR ReadOffEnd Operations Creates a rope reader with a text buffer of the given size; if size=0, uses default. Returns the current end char. This will be returned rather than giving ReadOffEnd error if CharForEndOfRope is true. get character, then increment reader location decrement reader location, then get character get character without incrementing reader location like Backwards, but doesn't change position Rope comparison operations that make use of readers for efficiency. uses readers rdr1 and rdr2 to read ropes r1 and r2 to test for equality uses readers rdr1 and rdr2 to read ropes r1 and r2 to test for equality returns TRUE if r1 starting at start1 is same as len chars of r2 starting at start2 returns FALSE if not enough chars available in either rope i.e., if start1+len > size[r1] or start2+len > size[r2] if rdr1 or rdr2 is NIL, gets own readers from cache uses readers rdr1 and rdr2 to compare ropes r1 and r2 returns less for r1 < r2; equal for r1 = r2; and greater for r1 > r2 if ~case then all characters forced lowercase for comparison uses readers rdr1 and rdr2 to compare substrings of ropes r1 and r2 if rdr1 or rdr2 is NIL, gets own readers from cache Scratch pool The next routines provide a small cache of rope readers to avoid creating a lot of garbage readers don't use these unless you are certain to free the reader at most once ok not to free it, but don't free it more than once Sets the default buffer size used by Create and readers in the cache. Plass, March 1, 1985 11:47:10 am PST Cleanup for Cedar 6.0 removed CharsArray stuff, and AppendToString, GetString, BackwardsGetString, AppendToText, GetText, BackwardsGetText (use Rope.AppendChars instead)., Peek, DIRECTORY, ROPE Κφ˜šΟc™Icodešœ Οmœ1™™>Jš™—š:™:Jš(™(J˜——š1™1Jš9™9J˜—še™eJ˜—šJ™JJš™Jš&™&J˜—š:™:Jš;™;Jš0™0———š ™ JšŸœŸœŸœ˜JšœŸœ˜J˜JšœŸœŸœ˜šœŸœŸœŸœ˜JšœŸœŸœ ˜2Jšœ ŸœB˜TJšœŸœŸœ˜-JšœŸœ˜+šœŸœŸœ˜"Jš4™4—Jšœ Ÿœ(˜;J˜—J˜Jšœ Ÿœ˜—š ™ šΟnœŸœŸœŸœ˜*J™T—J˜š‘œŸœŸœŸœ˜0JšœŸœŸœ˜"J˜—š‘œŸœŸœ Ÿœ˜1JšœŸœŸœ!˜2J˜—š ‘œŸœŸœŸœ Ÿœ˜=JšœŸœŸœ4˜EJ˜—š‘ œŸœŸœ Ÿœ˜;JšœŸœ˜ JšŸœŸœŸœŸœ˜?JšœU˜U˜J˜——š‘œŸœŸœ˜,JšœŸœ˜ šŸœ%Ÿ˜+JšœB˜B—šœ˜J˜——š‘ œŸœŸœ˜,JšœŸœ/˜7J˜—š‘ œŸœŸœ˜*JšœŸœ/˜7J˜—š‘ œŸœŸœ Ÿœ˜6JšœŸœŸœ˜%Jšœ™JšœV™VJ˜—š‘œŸœŸœŸœ˜6JšœŸœŸœ˜.J˜—š‘œŸœŸœ˜3JšœŸœ4Ÿœ˜CJ˜—š‘œŸœ˜)JšœŸœŸœ˜-J˜—JšœŸœŸœ)˜;Jš ‘œŸœŸœŸœŸœ˜@J˜š‘œŸœŸœŸœ˜&JšœŸœ˜ Jš-™-JšœŸœŸœ˜JšœŸœ˜JšŸœŸœŸœ ˜?JšŸœŸœ˜$J˜J˜—š‘ œŸœŸœŸœ˜,JšœŸœ˜ Jš-™-JšœŸœ˜JšŸœŸœŸœ#˜5JšŸœŸœ˜)J˜J˜—š‘œŸœŸœŸœ˜'JšœŸœ˜ Jš2™2JšœŸœŸœ˜JšœŸœ˜JšŸœŸœŸœ ˜%JšŸœŸœ˜$J˜J˜—š‘ œŸœŸœŸœ˜0JšœŸœ˜ Jš+™+JšœŸœ˜JšŸœŸœŸœ˜$JšŸœŸœ"˜-J˜——šC™Cš ‘œŸœ ŸœŸœŸœŸœ˜CJšG™GJšœŸœŸœ1˜CJ˜—š‘ œŸœ ŸœŸœŸœŸœŸœ˜_JšG™Gš0™0Jš"™"—š:™:Jš7™7—Jš3™3J˜—š‘œŸœ ŸœŸœŸœŸœŸœ˜cJš5™5Jšœœ ™DJš<™