-- RopeEditingAllocImpl.Mesa
-- written by Bill Paxton, March 1981
-- last edit by Bill Paxton, December 22, 1981 9:56 am
DIRECTORY
RopeEditingAlloc,
Rope,
RopeReader,
RopeFrom;
RopeEditingAllocImpl: CEDAR MONITOR
IMPORTS RopeReader, RopeFrom
EXPORTS RopeEditingAlloc =
BEGIN OPEN RopeEditingAlloc;
charsPerArray: NAT = RopeReader.charsPerArray;
wordsPerArray: NAT = charsPerArray/2;
charsArray: Chars ← NIL; -- current shared array of chars
charsRemaining: NAT ← 0; -- amount of room remaining in current chars array
charsRope: ROPE; -- rope pointing to current chars array
AllocChars: PUBLIC ENTRY PROC [len: NAT]
RETURNS [chars: Chars, start: NAT, base: ROPE] = {
-- returns chars array & starting index to fill with characters
-- and a rope that points to that substring of the chars array
IF len > charsRemaining THEN {
IF len > charsPerArray THEN ERROR;
IF charsPerArray-len < charsRemaining THEN { -- keep the current one
chars ← RopeFrom.pZone.NEW[CharsArray]; start ← 0;
base ← RopeReader.CharsRope[chars];
RETURN };
charsArray ← RopeFrom.pZone.NEW[CharsArray]; charsRemaining ← charsPerArray;
charsRope ← RopeReader.CharsRope[charsArray] };
chars ← charsArray;
start ← charsPerArray-charsRemaining;
charsRemaining ← charsRemaining-len;
base ← charsRope };
AllocWords: PUBLIC ENTRY PROC [nwords: NAT]
RETURNS [chars: Chars, start: NAT, base: ROPE] = {
-- ensures that start is even, i.e., start on word boundary
wordsRemaining: NAT;
IF nwords > (wordsRemaining ← charsRemaining/2) THEN {
IF nwords > wordsPerArray THEN ERROR;
IF wordsPerArray-nwords < wordsRemaining THEN {
chars ← RopeFrom.pZone.NEW[CharsArray]; start ← 0;
base ← RopeReader.CharsRope[chars];
RETURN };
charsArray ← RopeFrom.pZone.NEW[CharsArray];
wordsRemaining ← wordsPerArray;
charsRope ← RopeReader.CharsRope[charsArray] };
chars ← charsArray;
start ← (wordsPerArray-wordsRemaining)*2;
charsRemaining ← (wordsRemaining-nwords)*2;
base ← charsRope };
TryAllocAdjacent: PUBLIC ENTRY PROC [base: ROPE, start: NAT, len: NAT]
RETURNS [ok: BOOLEAN, chars: Chars] = {
IF base=charsRope AND
start=charsPerArray-charsRemaining AND
charsRemaining >= len THEN {
charsRemaining ← charsRemaining-len; RETURN [TRUE, charsArray]};
RETURN [FALSE, charsArray]};
-- ***** buffer cache
blockSize: NAT = 512;
blk1, blk2: REF TEXT; -- shared buffers
GetBlock: PUBLIC ENTRY PROC RETURNS [blk: REF TEXT] = {
IF blk2 # NIL THEN { blk ← blk2; blk2 ← NIL }
ELSE IF blk1 # NIL THEN { blk ← blk1; blk1 ← NIL }
ELSE blk ← RopeFrom.pZone.NEW[TEXT[blockSize]];
blk.length ← 0 };
FreeBlock: PUBLIC ENTRY PROC [blk: REF TEXT] = {
IF blk2 = NIL THEN blk2 ← blk ELSE IF blk1 = NIL THEN blk1 ← blk };
-- ***** Initialization
Start: PUBLIC PROC = {
};
END.