RopeFromFileImpl.Mesa
written by Bill Paxton, February 1981
Paxton, November 12, 1982 3:17 pm
Maxwell, January 5, 1983 12:11 pm
Russ Atkinson, July 26, 1983 5:28 pm
Paul Rovner, August 10, 1983 4:23 pm
Doug Wyatt, December 5, 1983 1:54 pm
DIRECTORY
Basics USING [bytesPerWord],
FS USING [defaultStreamOptions, OpenFile, StreamFromOpenFile, StreamOptions],
IO USING [GetBlock, GetIndex, GetLength, STREAM],
Rope,
RopeEdit,
RopeEditingAlloc,
RopeEditingBLT,
RopeFile USING [FromStream],
RopeFrom,
RopePrivate,
RopeReader;
RopeFromFileImpl: CEDAR MONITOR
IMPORTS
FS, IO, Rope, RopeEdit, RopeEditingAlloc, RopeEditingBLT, RopeFile, RopeFrom, RopePrivate
EXPORTS RopeFrom
SHARES Rope
= BEGIN OPEN RopeFrom, RopePrivate;
charsPerArray: NAT = RopeReader.charsPerArray;
charsPerSpace: NAT = charsPerArray;
spaceMin: NAT = charsPerSpace/2; -- put in shared array if less than 1/2
CharsArray: TYPE = RopeReader.CharsArray;
Chars: TYPE = REF CharsArray;
-- ***** Operations
File: PUBLIC PROC [
file: FS.OpenFile,
start: Offset ← 0,
byte address in file where rope will start
0 means first page after leader page
length: Offset ← MaxLen,
defaults to rest of file beyond start
activate: BOOLEANFALSE,
if activate is true, the system will start swapping the characters into real memory
fileLen: Offset ← MaxLen]
fileLen is # of bytes in file, excluding leader page (usually defaulted to rest of file)
RETURNS [rope: ROPE] = {
stream: IO.STREAMNIL;
options: FS.StreamOptions ← FS.defaultStreamOptions;
options[tiogaRead] ← FALSE; -- include the formatting information
options[closeFSOpenFileOnClose] ← FALSE; -- don't close the openFile
stream ← FS.StreamFromOpenFile[
openFile: file, accessRights: $read, streamOptions: options,
streamBufferParms: [vmPagesPerBuffer: 2, nBuffers: 1]];
RETURN[RopeFile.FromStream[stream: stream, start: start, len: length]];
};
Stream: PUBLIC PROC [stream: IO.STREAM, length: Offset ← MaxLen]
RETURNS [rope: ROPE] = {
MakeRope: PROC [len: Offset] RETURNS [ROPE] = {
chars: REF RopeReader.CharsArray;
start, nchars, charloc: NAT;
base: ROPE;
IF len = 0 THEN RETURN [NIL];
IF len > charsPerSpace THEN { -- split into balanced parts
half: Offset = MAX[len/2,charsPerSpace];
front: ROPE = MakeRope[half]; -- ensure proper evaluation order! front first
back: ROPE = MakeRope[len-half]; -- then the back
RETURN [Rope.Concat[front,back]];
};
nchars ← Short[len];
[chars, start, base] ← RopeEditingAlloc.AllocWords[
(nchars+(Basics.bytesPerWord-1))/Basics.bytesPerWord];
charloc ← start;
UNTIL nchars = 0 DO
nread: NAT;
block.length ← 0;
nread ← IO.GetBlock[self: stream, block: block, startIndex: 0, count: nchars];
RopeEditingBLT.StringToArrayBlt[block,0,chars,charloc,nread];
nchars ← nchars-nread; charloc ← charloc+nread;
ENDLOOP;
RETURN [qZone.NEW[Tsubstr ← [node[substr[len,base,start,1+RopeEdit.Depth[base]]]]]] };
start,fileLen: Offset;
block: REF TEXT;
fileLen ← IO.GetLength[stream];
start ← IO.GetIndex[stream];
IF fileLen <= start THEN RETURN [NIL];
length ← MIN[length,fileLen-start];
IF length = 0 THEN RETURN [NIL];
block ← RopeEditingAlloc.GetBlock[];
rope ← MakeRope[length];
RopeEditingAlloc.FreeBlock[block];
};
-- ***** Initialization
StartRopeFromFile: PUBLIC PROC = {
};
END.