<> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<[rope,index] _ RopeReader.Position[reader];>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> DIRECTORY Basics USING [Comparison], Rope USING [MaxLen, ROPE, Text]; RopeReader: CEDAR DEFINITIONS = BEGIN <<***** RopeReader Declarations>> ROPE: TYPE = Rope.ROPE; Offset: TYPE = INT; 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; <<***** RopeReader Operations>> 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 GetIndex[reader]=index THEN RETURN; 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> text: REF TEXT ~ reader.text; i: NAT ~ reader.current; IF i>0 THEN RETURN[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> text: REF TEXT ~ reader.text; i: NAT ~ reader.current; IF i>0 THEN RETURN[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 [BOOLEAN]; <> <> <> <> < size[r1] or start2+len > size[r2]>> <> Compare: PROC [r1,r2: ROPE, rdr1,rdr2: Ref _ NIL, case: BOOLEAN _ TRUE] RETURNS [Basics.Comparison] = INLINE { <> < r2>> <> 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: BOOLEAN _ TRUE] RETURNS [Basics.Comparison]; <> <> <> AppendToString: PROC[str: REF TEXT, rope: ROPE, start: INT _ 0, len: INT _ LAST[INT]] RETURNS [count: NAT]; <> <> GetString: PROC [reader: Ref, str: REF TEXT, length: NAT _ LAST[NAT]] RETURNS [count: NAT]; <> <> BackwardsGetString: PROC [reader: Ref, str: REF TEXT, length: NAT _ LAST[NAT]] RETURNS [count: NAT]; <> <> AppendToText: PROC[txt: Rope.Text, rope: ROPE, start: INT _ 0, len: INT _ LAST[INT]] RETURNS [count: NAT] = TRUSTED INLINE { count _ AppendToString[str: LOOPHOLE[txt], rope: rope, start: start, len: len] }; <> <> GetText: PROC [reader: Ref, txt: Rope.Text, length: NAT _ LAST[NAT]] RETURNS [count: NAT] = TRUSTED INLINE { count _ GetString[reader: reader, str: LOOPHOLE[txt], length: length] }; <> <> BackwardsGetText: PROC [reader: Ref, txt: Rope.Text, length: NAT _ LAST[NAT]] RETURNS [count: NAT] = TRUSTED INLINE { count _ BackwardsGetString[reader: reader, str: LOOPHOLE[txt], length: length] }; <> <> <<***** Private declarations>> charsPerPage: NAT = 512; pagesPerArray: NAT = 16; charsPerArray: NAT = charsPerPage*pagesPerArray; Chars: TYPE = REF READONLY CharsArray; CharsArray: TYPE = PACKED ARRAY [0..charsPerArray) OF CHAR; CharsRope: PROC [chars: Chars] RETURNS [ROPE]; <> AppendToChars: PROC[chars: REF CharsArray, offset: NAT _ 0, rope: ROPE, start: INT _ 0, len: INT _ LAST[INT]] RETURNS [count: NAT]; <> <> GetChars: PROC [ reader: Ref, chars: REF CharsArray, length: NAT _ LAST[NAT], offset: NAT _ 0] RETURNS [count: NAT]; <> BackwardsGetChars: PROC [ reader: Ref, chars: REF CharsArray, length: NAT _ LAST[NAT], offset: NAT _ 0] RETURNS [count: NAT]; <> <> <> <> GetRopeReader: PROC RETURNS [reader: Ref]; FreeRopeReader: PROC [reader: Ref]; SetDefaultSize: PROC[size: NAT]; <> <<>> END.