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: NAT ← LAST[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: NAT ← LAST[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: NAT ← LAST[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: NAT ← LAST[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: NAT ← LAST[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: NAT ← LAST[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.