<<>> <> <> <> <> <> <> <> <> DIRECTORY Basics USING [BoundsCheck, Comparison, RawBytes], Rope USING [ActionType, Compare, Equal, Find, Map, Match, SkipOver, SkipTo, ROPE, Text, TextBound]; RefText: CEDAR DEFINITIONS IMPORTS Basics, Rope = BEGIN <> <> <> <> <> < s.length THEN BoundsFault ELSE len _ MIN[len, s.length-start].>> <> <> <> <> PureText: TYPE = REF READONLY TEXT; ROPE: TYPE = Rope.ROPE; MaxLen: TextBound = TextBound.LAST; TextBound: TYPE = Rope.TextBound; <> New: PROC [nChars: TextBound] RETURNS [REF TEXT]; <= nChars, and returns a REF to it.>> <<>> <> Error: ERROR [ec: ErrorCode]; ErrorCode: TYPE = { clientModifiedReleasedText }; <> ObtainScratch: PROC [nChars: TextBound ¬ line] RETURNS [REF TEXT]; <> <= nChars. This TEXT is generally obtained from a pool of TEXTs.>> <> <> <> line: TextBound = 100; page: TextBound = 512; <> <<>> ReleaseScratch: PROC [t: REF TEXT]; <> <> <> Append: PROC [to: REF TEXT, from: PureText, start: TextBound ¬ 0, len: TextBound ¬ MaxLen] RETURNS [REF TEXT]; <> < to.maxLength or length of result text would exceed MaxLen)>> <<>> AppendTextRope: PROC [to: REF TEXT, from: Rope.Text, start: TextBound ¬ 0, len: TextBound ¬ MaxLen] RETURNS [REF TEXT] = INLINE { <> < to.maxLength or length of result text would exceed MaxLen)>> RETURN[Append[to, TrustTextRopeAsText[from], start, len]]; }; AppendRope: PROC [to: REF TEXT, from: ROPE, start: INT ¬ 0, len: TextBound ¬ MaxLen] RETURNS [REF TEXT]; <> < to.maxLength or length of result text would exceed MaxLen)>> <<>> AppendChar: PROC [to: REF TEXT, from: CHAR] RETURNS [REF TEXT]; <> < to.maxLength or length of result text would exceed MaxLen)>> <<>> InlineAppendChar: PROC [to: REF TEXT, from: CHAR] RETURNS [REF TEXT] = INLINE { <> < to.maxLength or length of result text would exceed MaxLen)>> IF to.length >= to.maxLength THEN RETURN [AppendChar[to, from]]; to[to.length] ¬ from; to.length ¬ to.length + 1; RETURN [to]; }; ReserveChars: PROC [to: REF TEXT, nChars: TextBound] RETURNS [REF TEXT]; <> <> <> <= to.length + nChars).>> <<>> InlineReserveChars: PROC [to: REF TEXT, nChars: TextBound] RETURNS [REF TEXT] = INLINE { <> <> IF LOOPHOLE[to.maxLength, INTEGER]-LOOPHOLE[nChars, INTEGER] < LOOPHOLE[to.length, INTEGER] THEN RETURN [ReserveChars[to, nChars]]; RETURN [to]; }; <<>> <> Compare: PROC [s1, s2: PureText, case: BOOL ¬ TRUE] RETURNS [Basics.Comparison] = INLINE { <> < case of characters is significant>> RETURN [Rope.Compare[TrustTextAsRope[s1], TrustTextAsRope[s2], case]]; }; Equal: PROC [s1, s2: PureText, case: BOOL ¬ TRUE] RETURNS [BOOL] = INLINE { <> RETURN [Rope.Equal[TrustTextAsRope[s1], TrustTextAsRope[s2], case]]; }; Fetch: PROC [base: PureText, index: TextBound] RETURNS [CHAR] = INLINE { <= base.length)>> <> RETURN [base[Basics.BoundsCheck[index, Length[base]]]]; }; Find: PROC [s1, s2: PureText, pos1: TextBound ¬ 0, case: BOOL ¬ TRUE] RETURNS [INTEGER] = INLINE { <> <> <= Length[s1])>> RETURN [Rope.Find[TrustTextAsRope[s1], TrustTextAsRope[s2], pos1, case]]; }; Length: PROC [base: PureText] RETURNS [TextBound] = INLINE { <> RETURN [IF base = NIL THEN 0 ELSE base.length]; }; ActionType: TYPE = PROC[CHAR] RETURNS[BOOL]; <> Map: PROC [s: PureText, start: TextBound ¬ 0, len: TextBound ¬ MaxLen, action: ActionType] RETURNS [quit: BOOL] = INLINE { < s.length)>> <> <> RETURN [Rope.Map[TrustTextAsRope[s], start, len, action]]; }; Match: PROC [pattern, object: PureText, case: BOOL ¬ TRUE] RETURNS [BOOL] = INLINE { <> <> RETURN [Rope.Match[TrustTextAsRope[pattern], TrustTextAsRope[object], case]]; }; SkipTo: PROC [s: PureText, pos: TextBound ¬ 0, skip: PureText] RETURNS [TextBound] = INLINE { <> RETURN [Rope.SkipTo[TrustTextAsRope[s], pos, TrustTextAsRope[skip]]]; }; SkipOver: PROC [s: PureText, pos: TextBound ¬ 0, skip: PureText] RETURNS [TextBound] = INLINE { <> RETURN [Rope.SkipOver[TrustTextAsRope[s], pos, TrustTextAsRope[skip]]]; }; <<>> <> Literal: PROC [text: REF TEXT] RETURNS [REF TEXT] ~ INLINE { RETURN[text] }; <> TrustTextAsRope: PROC [text: PureText] RETURNS [Rope.Text] = TRUSTED INLINE { <> <<1. You do NOT alter the text while there is a ROPE reference to the object>> <<2. You do not care about the runtime type of the object>> RETURN [LOOPHOLE[text]]; }; <<>> TrustTextRopeAsText: PROC [rope: Rope.Text] RETURNS [PureText] = TRUSTED INLINE { <> <> RETURN [LOOPHOLE[rope]]; }; BasePointer: TYPE ~ POINTER TO Basics.RawBytes; BaseFromTextPointer: PROC [p: POINTER--TO TEXT--] RETURNS [BasePointer] = TRUSTED INLINE { RETURN[LOOPHOLE[p, BasePointer]+SIZE[TEXT[0]]] }; BaseFromText: PROC [text: PureText] RETURNS [BasePointer] = TRUSTED INLINE { RETURN[BaseFromTextPointer[LOOPHOLE[text]]] }; BaseFromTextRope: PROC [rope: Rope.Text] RETURNS [BasePointer] = TRUSTED INLINE { RETURN[BaseFromTextPointer[LOOPHOLE[rope]]] }; END.