<<>> <> <> <> <> <> <> <> <> <> <> <> DIRECTORY Basics USING [Comparison], Rope USING [MaxLen, ROPE]; RopeReader: CEDAR DEFINITIONS ~ BEGIN <> <> <> <> <> <> <> <> <<[rope,index] _ RopeReader.Position[reader];>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> 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 i> i: NAT ~ reader.current; IF i>0 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 i> i: NAT ~ reader.current; IF i>0 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]; <> <> <> <> < size[r1] or start2+len > size[r2]>> <> Compare: PROC [r1,r2: ROPE, rdr1,rdr2: Ref ¬ NIL, case: BOOLEAN ¬ TRUE] RETURNS [Basics.Comparison] <> < r2>> <> ~ 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. <> <> <> <<>> <<>> <<>> <<>> <<>>