RopeReaderGetImpl.mesa
written by Bill Paxton, January 1981
McGregor, September 10, 1982 11:08 am
Maxwell, January 5, 1983 12:06 pm
Russ Atkinson, July 22, 1983 3:34 pm
Paul Rovner, August 10, 1983 4:22 pm
DIRECTORY
RopeReader,
RopeEditingBLT,
Rope,
RopePrivate;
RopeReaderGetImpl: CEDAR PROGRAM
IMPORTS RopeReader, Rope, RopePrivate, RopeEditingBLT
EXPORTS RopeReader
SHARES RopeReader, Rope =
BEGIN OPEN RopeReader, RopePrivate;
Text: TYPE = Rope.Text;
String: TYPE = REF TEXT;
GetText: PUBLIC PROC
[reader: Ref, txt: Text, length: NATLAST[NAT]] RETURNS [count: NAT] = {
rope: ROPE;
start: Offset;
offset: NAT ← txt.length;
[rope, start] ← Position[reader];
count ← Short[MIN[length, Rope.InlineSize[rope]-start, txt.max-offset]];
GTxt[rope, start, txt, offset, count];
SetPosition[reader, rope, start+count];
txt.length ← txt.length+count};
BackwardsGetText: PUBLIC PROC
[reader: Ref, txt: Text, length: NATLAST[NAT]] RETURNS [count: NAT] = {
rope: ROPE;
start: Offset;
offset: NAT ← txt.length;
[rope, start] ← Position[reader];
count ← Short[MIN[length, start, txt.max-offset]];
GTxt[rope, start ← start-count, txt, offset, count];
SetPosition[reader, rope, start];
txt.length ← txt.length+count};
GetString: PUBLIC PROC
[reader: Ref, str: String, length: NATLAST[NAT]] RETURNS [count: NAT] = {
rope: ROPE;
start: Offset;
offset: NAT ← str.length;
[rope, start] ← Position[reader];
count ← Short[MIN[length, Rope.InlineSize[rope]-start, str.maxLength-offset]];
GTxt[rope, start, str, offset, count];
SetPosition[reader, rope, start+count];
str.length ← str.length+count;};
BackwardsGetString: PUBLIC PROC
[reader: Ref, str: String, length: NATLAST[NAT]]
RETURNS [count: NAT] = {
rope: ROPE;
start: Offset;
offset: NAT ← str.length;
[rope, start] ← Position[reader];
count ← Short[MIN[length, start, str.maxLength-offset]];
GTxt[rope, start ← start-count, str, offset, count];
SetPosition[reader, rope, start];
str.length ← str.length+count};
GetChars: PUBLIC PROC [
reader: Ref,
chars: REF CharsArray,
length: NATLAST[NAT],
offset: NAT ← 0]
RETURNS [count: NAT] = {
rope: ROPE;
start: Offset;
[rope, start] ← Position[reader];
count ← Short[MIN[length, Rope.InlineSize[rope]-start, charsPerArray-offset]];
GTxt[rope, start, chars, offset, count];
SetPosition[reader, rope, start+count]};
BackwardsGetChars: PUBLIC PROC [
reader: Ref, chars: REF CharsArray,
length: NATLAST[NAT],
offset: NAT ← 0]
RETURNS [count: NAT] = {
rope: ROPE;
start: Offset;
[rope, start] ← Position[reader];
count ← Short[MIN[length, start, charsPerArray-offset]];
GTxt[rope, start ← start-count, chars, offset, count];
SetPosition[reader, rope, start]};
GTxt: PROC
[base: ROPE, start: Offset, b: REF, offset, len: NAT] = TRUSTED {
loc: NAT ← offset;
WHILE len # 0 DO WITH x:base SELECT FROM
text => {
st: NAT ← Short[start];
rem: NAT ← Short[x.length]-st;
IF rem > len THEN rem ← len;
WITH b SELECT FROM
chars: REF CharsArray => RopeEditingBLT.TextToArrayBlt[to:chars, toLoc:loc, nChars:rem,
from:@x, fromLoc:st];
txt: Text => RopeEditingBLT.TextToTextBlt[to:txt, toLoc:loc, nChars:rem,
from:@x, fromLoc:st];
str: String => RopeEditingBLT.TextToStringBlt[to:str, toLoc:loc, nChars:rem,
from:@x, fromLoc:st];
ENDCASE => ERROR;
RETURN };
node => WITH x:x SELECT FROM
object => WITH x.base SELECT FROM
y: Chars => {
st: NAT ← Short[start];
rem: NAT ← Short[x.size]-st;
IF rem > len THEN rem ← len;
WITH b SELECT FROM
chars: REF CharsArray =>
RopeEditingBLT.ArrayToArrayBlt[to:chars, toLoc:loc, nChars:rem,
from:y, fromLoc:st];
txt: Text =>
RopeEditingBLT.ArrayToTextBlt[to:txt, toLoc:loc, nChars:rem,
from:y, fromLoc:st];
str: String =>
RopeEditingBLT.ArrayToStringBlt[to:str, toLoc:loc, nChars:rem,
from:y, fromLoc:st];
ENDCASE => ERROR;
RETURN };
ENDCASE => {
piecemap: Rope.PieceMapType ← x.pieceMap;
data: REF ← x.base;
fetch: Rope.FetchType ← x.fetch;
rem: Offset ← NonNeg[x.size-start];
IF rem < len THEN {
IF rem = 0 THEN EXIT ELSE len ← rem};
IF piecemap # NIL THEN {
action: SAFE PROC [base:ROPE, start: INT, len: INT]
RETURNS [quit: BOOL ← FALSE] = TRUSTED {
ln: NAT ← Short[len];
GTxt[base, start, b, loc, ln]; loc ← loc + ln;
RETURN [FALSE]};
[] ← piecemap[data, start, len, action]}
ELSE WITH b SELECT FROM
txt: Text =>
FOR i: Offset IN [start..start+len) DO
txt[loc] ← fetch[data,i]; loc ← loc+1; ENDLOOP;
chars: REF CharsArray =>
FOR i: Offset IN [start..start+len) DO
chars[loc] ← fetch[data,i]; loc ← loc+1; ENDLOOP;
str: String =>
FOR i: Offset IN [start..start+len) DO
str[loc] ← fetch[data,i]; loc ← loc+1; ENDLOOP;
ENDCASE => ERROR;
EXIT};
substr => {
rem: Offset ← NonNeg[x.size-start];
IF rem < len THEN {
IF rem = 0 THEN EXIT ELSE len ← rem};
start ← start + x.start; base ← x.base; LOOP};
concat => {
xpos: Offset ← x.pos;
rem: Offset ← NonNeg[x.size-start];
IF rem < len THEN {
IF rem = 0 THEN EXIT ELSE len ← rem};
IF start+len <= xpos THEN {base ← x.base; LOOP};
IF start < xpos THEN {
subLen: NAT ← Short[xpos-start];
GTxt[x.base, start, b, loc, subLen];
start ← 0; len ← len - subLen; loc ← loc + subLen}
ELSE start ← start - xpos;
base ← x.rest; LOOP };
replace => {
xstart: Offset ← x.start;
xnew: Offset ← x.newPos;
rem: Offset ← NonNeg[x.size-start];
IF rem < len THEN
{IF rem = 0 THEN EXIT ELSE len ← rem};
IF start < xstart THEN
{subLen: NAT;
IF xstart-start >= len THEN {base ← x.base; LOOP};
subLen ← Short[xstart-start];
GTxt[x.base, start, b, loc, subLen];
start ← xstart; len ← len - subLen; loc ← loc + subLen};
IF start < xnew THEN
{subLen: NAT;
st: Offset ← start - xstart;
IF xnew-start >= len THEN
{start ← st; base ← x.replace; LOOP};
subLen ← Short[xnew-start];
GTxt[x.replace, st, b, loc, subLen];
start ← xnew; len ← len - subLen; loc ← loc + subLen};
start ← start - xnew + x.oldPos; base ← x.base; LOOP};   
ENDCASE => { IF base # NIL THEN ERROR Rope.NoRope;
IF len = 0 THEN EXIT ELSE ERROR};
ENDCASE => { IF base # NIL THEN ERROR Rope.NoRope;
IF len = 0 THEN EXIT ELSE ERROR};
ENDLOOP};
-- ***** Initialization
StartRopeReaderGet: PUBLIC PROC = {};
END.