<> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<[rope,index] _ RopeReader.Position[reader];>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> DIRECTORY Basics, Rope; RopeReader: CEDAR DEFINITIONS = BEGIN <<***** RopeReader Declarations>> Ref: TYPE = REF Body; -- Body of reader is a private record (declared below) ROPE: TYPE = Rope.ROPE; Offset: TYPE = INT; MaxLen: Offset = Rope.MaxLen; ReadOffEnd: ERROR; <<***** RopeReader Operations>> Create: PROC RETURNS [Ref]; SetPosition: PROC [reader: Ref, rope: ROPE, index: Offset _ 0] = INLINE { IF GetRope[reader]#rope OR GetIndex[reader]#index THEN { reader.current _ reader.first _ reader.after _ 0; reader.chars _ NIL; reader.text _ NIL; reader.rope _ rope; reader.index _ index}}; SetIndex: PROC [reader: Ref, index: Offset _ 0] = INLINE { IF GetIndex[reader]#index THEN { reader.current _ reader.first _ reader.after _ 0; reader.chars _ NIL; reader.text _ NIL; reader.index _ index}}; BackupIndex: PROC [reader: Ref, amount: Offset] = INLINE { SetIndex[reader, GetIndex[reader]-amount] }; BumpIndex: PROC [reader: Ref, amount: Offset] = INLINE { SetIndex[reader, GetIndex[reader]+amount] }; Position: PROC [reader: Ref] RETURNS [rope: ROPE, index: Offset] = INLINE { RETURN [reader.rope, reader.index+reader.current-reader.first] }; GetRope: PROC [reader: Ref] RETURNS [rope: ROPE] = INLINE { RETURN [reader.rope] }; GetIndex: PROC [reader: Ref] RETURNS [index: Offset] = INLINE { RETURN [reader.index+reader.current-reader.first] }; 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 }; ReaderProc: TYPE = PROC [reader: Ref] RETURNS [CHAR]; Get: ReaderProc = INLINE { <> current: NAT; IF (current_reader.current) >= reader.after THEN RETURN[ReadChar[reader,get]]; reader.current _ current+1; RETURN[IF reader.txtFlag THEN reader.text[current] ELSE reader.chars[current]]}; Backwards: ReaderProc = INLINE { <> current: NAT; IF (current_reader.current) <= reader.first THEN RETURN[ReadChar[reader,backwards]]; reader.current _ current _ current-1; RETURN[IF reader.txtFlag THEN reader.text[current] ELSE reader.chars[current]]}; Peek: ReaderProc = INLINE { <> current: NAT; IF (current_reader.current) >= reader.after THEN RETURN[ReadChar[reader,peek]]; RETURN[IF reader.txtFlag THEN reader.text[current] ELSE reader.chars[current]]}; PeekBackwards: ReaderProc = INLINE { <> current: NAT; IF (current_reader.current) <= reader.first THEN RETURN[ReadChar[reader,peekbackwards]]; RETURN[IF reader.txtFlag THEN reader.text[current-1] ELSE reader.chars[current-1]]}; Mode: PRIVATE TYPE = {get, backwards, peek, peekbackwards}; ReadChar: PRIVATE PROC [reader: Ref, mode: Mode] RETURNS [CHAR]; <> 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: Offset, 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: Offset, rdr1,rdr2: Ref _ NIL, case: BOOLEAN _ TRUE] RETURNS [Basics.Comparison]; <> <> <> GetText: PROC [reader: Ref, txt: Rope.Text, length: NAT _ LAST[NAT]] RETURNS [count: NAT]; <> <> BackwardsGetText: PROC [reader: Ref, txt: Rope.Text, length: NAT _ LAST[NAT]] 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]; <> <> <<***** Private declarations>> Chars: TYPE = REF READONLY CharsArray; -- CharsArray is a packed array of characters CharsRope: PROC [chars: Chars] RETURNS [ROPE]; <> 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]; Body: TYPE = PRIVATE RECORD [ current: NAT _ 0, -- index of current character first: NAT _ 0, -- index of first character to read after: NAT _ 0, -- index beyond last character to read chars: Chars, -- character array that we are currently reading text: Rope.Text, -- text rope that we are currently reading rope: ROPE, -- rope that we are reading index: Offset _ 0, -- index in rope of first character txtFlag: BOOLEAN _ FALSE, -- if true, read from text. else read from chars charForEndOfRope: BOOLEAN _ FALSE, <> endChar: CHAR _ 0C -- char to return when reach end of rope ]; charsPerPage: NAT = 512; pagesPerArray: NAT = 16; charsPerArray: NAT = charsPerPage*pagesPerArray; CharsArray: TYPE = PACKED ARRAY [0..charsPerArray) OF CHAR; StartRopeReader, StartRopeReaderMisc, StartRopeReaderGet: PROC; END.