<> <> <> <> <> <> <<>> DIRECTORY Rope USING [ROPE], RopeEditingAlloc USING [], RopeReader USING [CharsArray, charsPerArray, CharsRope]; RopeEditingAllocImpl: CEDAR MONITOR IMPORTS RopeReader EXPORTS RopeEditingAlloc = { ROPE: TYPE = Rope.ROPE; Chars: TYPE = REF CharsArray; CharsArray: TYPE = RopeReader.CharsArray; 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] = { <> <> IF len > charsRemaining THEN { IF len > charsPerArray THEN ERROR; IF charsPerArray-len < charsRemaining THEN { -- keep the current one chars _ NEW[CharsArray]; start _ 0; base _ RopeReader.CharsRope[chars]; RETURN }; charsArray _ 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] = { <> wordsRemaining: NAT; IF nwords > (wordsRemaining _ charsRemaining/2) THEN { IF nwords > wordsPerArray THEN ERROR; IF wordsPerArray-nwords < wordsRemaining THEN { chars _ NEW[CharsArray]; start _ 0; base _ RopeReader.CharsRope[chars]; RETURN }; charsArray _ 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 _ NIL; -- 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 _ 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; }; }.