RopeParts.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Last tweaked by Mike Spreitzer on October 5, 1990 7:51:52 am PDT
A RopePart represents the same thing as a ROPE: an immutable object containg a sequence of characters, indexed starting at 0 for Length characters. The difference is in the costs of the representation: a RopePart takes 3 times as much stack space, and admits a Substr implementation that does no heap allocation. Many procedures in this interface have the same names and semantics as those in the Rope interface.
DIRECTORY Basics, Rope;
RopeParts: CEDAR DEFINITIONS
IMPORTS Rope
= BEGIN
Part 1: Basic operations and definitions
RopePart: TYPE ~ RECORD [base: ROPE, start, len: INT];
Invariant: 0 <= start <= start+len <= base.Length.
No guarantees about what the following procedures do with a broken RopePart.
ROPE: TYPE = Rope.ROPE;
nil: RopePart ~ [NIL, 0, 0]; --one of the possible representations of the empty sequence
MaxLen: INT ~ Rope.MaxLen;
Make: PROC [base: ROPE, start: INT ← 0, len: INT ← MaxLen] RETURNS [RopePart];
Returns a RopePart that represents the same sequence as Rope.Substr[base, start, len].
InlineMake: PROC [base: ROPE, start: INT ← 0, len: INT ← MaxLen] RETURNS [RopePart]
~ INLINE {limit: INT ~ base.InlineLength[];
IF start>limit THEN RETURN [nil];
RETURN [[base, start, MIN[len, limit-start]]]};
FromChar: PROC [CHAR] RETURNS [RopePart];
ToRope: PROC [RopePart] RETURNS [ROPE];
InlineToRope: PROC [rp: RopePart] RETURNS [ROPE]
~ INLINE {RETURN rp.base.Substr[start: rp.start, len: rp.len]};
Simplify: PROC [rp: RopePart, start, end: BOOLTRUE] RETURNS [RopePart];
start => result.start = 0.
end => result.start+result.len = result.base.Length.
Cat: PROC [r1, r2, r3, r4, r5: RopePart ← nil] RETURNS [RopePart];
Concat: PROC [base, rest: RopePart ← nil] RETURNS [RopePart];
EasyConcat: PROC [base, rest: RopePart ← nil] RETURNS [BOOL, RopePart];
Returns [TRUE, concatenation] if it can be done without allocating; otherwise, returns [FALSE, nil].
Compare: PROC [s1, s2: RopePart, case: BOOLTRUE] RETURNS [Basics.Comparison];
Equal: PROC [s1, s2: RopePart, case: BOOLTRUE] RETURNS [BOOL];
EqualToRope: PROC [s1: RopePart, s2: ROPE, case: BOOLTRUE] RETURNS [BOOL];
Fetch: PROC [base: RopePart, index: INT ← 0] RETURNS [c: CHAR];
InlineFetch: PROC [base: RopePart, index: INT] RETURNS [c: CHAR]
~ INLINE {RETURN base.base.InlineFetch[base.start+index]};
Index: PROC [s1, s2: RopePart, pos1: INT ← 0, case: BOOLTRUE, clipBeforeSeek: BOOLFALSE] RETURNS [INT];
Like Rope.Index. clipBeforeSeek says it would be better to allocate a smaller rope than to search, in s1.base, past the end of the range relevent to s1.
Find: PROC [s1, s2: RopePart, pos1: INT ← 0, case: BOOLTRUE, clipBeforeSeek: BOOLFALSE] RETURNS [INT];
FindBackward: PROC [s1, s2: RopePart, pos1: INT ← MaxLen, case: BOOLTRUE, clipBeforeSeek: BOOLFALSE] RETURNS [INT];
IsEmpty: PROC [RopePart] RETURNS [BOOL];
InlineIsEmpty: PROC [r: RopePart] RETURNS [BOOL]
~ INLINE {RETURN[r.len = 0]};
Length: PROC [base: RopePart] RETURNS [INT];
InlineLength: PROC [base: RopePart] RETURNS [INT]
~ INLINE {RETURN[base.len]};
Size: PROC [base: RopePart] RETURNS [INT];
Size[base] = Length[base]
InlineSize: PROC [base: RopePart] RETURNS [INT]
~ INLINE {RETURN[base.len]};
Substr: PROC [base: RopePart, start: INT ← 0, len: INT ← MaxLen] RETURNS [RopePart];
Replace: PROC [base: RopePart, start: INT ← 0, len: INT ← MaxLen, with: RopePart ← nil] RETURNS [RopePart];
ReplaceElt: PROC [base: RopePart, index: INT, with: CHAR] RETURNS [RopePart];
Part 2: Extended operations and definitions
ActionType: TYPE ~ Rope.ActionType;
TranslatorType: TYPE ~ Rope.TranslatorType;
Run: PROC [s1: RopePart, pos1: INT ← 0, s2: RopePart, pos2: INT ← 0, case: BOOLTRUE] RETURNS [INT];
IsPrefix: PROC [prefix, subject: RopePart, case: BOOLTRUE] RETURNS [BOOL];
IsSuffix: PROC [suffix, subject: RopePart, case: BOOLTRUE] RETURNS [BOOL];
Match: PROC [pattern, object: RopePart, case: BOOLTRUE] RETURNS [BOOL];
SkipTo: PROC [s: RopePart, pos: INT ← 0, skip: RopePart] RETURNS [INT];
SkipOver: PROC [s: RopePart, pos: INT ← 0, skip: RopePart] RETURNS [INT];
Map: PROC [base: RopePart, action: ActionType] RETURNS [BOOL];
Translate: PROC [base: RopePart, translator: TranslatorType ← NIL] RETURNS [RopePart];
ToRefText: PROC [base: RopePart] RETURNS [REF TEXT];
AppendChars: PROC [to: REF TEXT, from: RopePart] RETURNS [charsMoved: NAT];
UnsafeMoveChars: UNSAFE PROC [to: Basics.UnsafeBlock, from: RopePart] RETURNS [charsMoved: INT];
Hash: PROC [base: RopePart, case: BOOLTRUE, seed: CARDINAL ← defaultSeed] RETURNS [CARDINAL];
defaultSeed: CARDINAL ~ 31415;
END.