FSRopeImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Doug Wyatt, June 24, 1985 7:11:58 pm PDT
Michael Plass, March 25, 1986 3:47:49 pm PST
Makes an FS.OpenFile from a ROPE.
FS.StreamFromOpenFile[FSRope.Open[rope]] should produce a faster stream than IO.RIS[rope].
DIRECTORY
Basics USING [bytesPerWord],
BasicTime USING [GMT, nullGMT],
FS USING [Lock, OpenFile, PagesForBytes, StreamFromOpenFile, WordsForPages],
FSBackdoor USING [CreateFileProcs, CreateProcsOpenFile, FileProcs, ProduceError],
FSRope USING [],
IO USING [STREAM],
PrincOpsUtils USING [LongCopy],
RefText USING [ObtainScratch, ReleaseScratch],
Rope USING [AppendChars, ROPE, Size];
FSRopeImpl: CEDAR PROGRAM
IMPORTS FS, FSBackdoor, PrincOpsUtils, RefText, Rope
EXPORTS FSRope
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
Data: TYPE ~ REF DataRep;
DataRep: TYPE ~ RECORD [
rope: ROPE, -- the underlying rope
bytes: INT, -- Rope.Size[rope]
pages: INT -- FS.PagesForBytes[bytes]
];
wordsPerPage: NAT ~ FS.WordsForPages[1];
bytesPerPage: NAT ~ wordsPerPage*Basics.bytesPerWord;
ropeFileProcs: REF FSBackdoor.FileProcs ~ FSBackdoor.CreateFileProcs[
GetClass: RopeGetClass, GetName: RopeGetName, GetInfo: RopeGetInfo, Read: RopeRead];
RopeGetClass: PROC [clientFile: REF] RETURNS [ATOM] ~ {
RETURN[$ROPE];
};
RopeGetName: PROC [clientFile: REF] RETURNS [fullFName, attachedTo: ROPE] ~ {
RETURN[fullFName: "-- from FSRope --", attachedTo: NIL];
};
RopeGetInfo: PROC [clientFile: REF] RETURNS [keep: CARDINAL,
pages, bytes: INT, created: BasicTime.GMT, lock: FS.Lock] ~ {
data: Data ~ NARROW[clientFile];
RETURN[keep: 1, pages: data.pages, bytes: data.bytes, created: BasicTime.nullGMT, lock: read];
};
RopeRead: UNSAFE PROC [clientFile: REF, from, nPages: INT, to: LONG POINTER] ~ {
data: Data ~ NARROW[clientFile];
SELECT TRUE FROM
from NOT IN[0..data.pages) => FSBackdoor.ProduceError[code: unknownPage,
explanation: "Tried to read a page that is not in the file"];
nPages > (data.pages-from) => FSBackdoor.ProduceError[code: unknownPage,
explanation: "Tried to read a page that is not in the file"];
ENDCASE => {
buffer: REF TEXT ~ RefText.ObtainScratch[bytesPerPage];
FOR i: INT IN [0..nPages) DO
start: INT ~ (from+i)*bytesPerPage;
buffer.length ← 0;
[] ← Rope.AppendChars[buffer: buffer, rope: data.rope, start: start, len: bytesPerPage];
TRUSTED {
srcPointer: LONG POINTER ~ LOOPHOLE[buffer, LONG POINTER]+SIZE[TEXT[0]];
dstPointer: LONG POINTER ~ to+i*wordsPerPage;
PrincOpsUtils.LongCopy[from: srcPointer, nwords: wordsPerPage, to: dstPointer];
};
ENDLOOP;
RefText.ReleaseScratch[buffer];
};
};
OpenFileFromRope: PUBLIC PROC [rope: ROPE] RETURNS [FS.OpenFile] ~ {
bytes: INT ~ Rope.Size[rope];
pages: INT ~ FS.PagesForBytes[bytes];
data: Data ~ NEW[DataRep ← [rope: rope, bytes: bytes, pages: pages]];
RETURN[FSBackdoor.CreateProcsOpenFile[clientFile: data, fileProcs: ropeFileProcs]];
};
StreamFromRope: PUBLIC PROC [rope: ROPE] RETURNS [STREAM] ~ {
RETURN[FS.StreamFromOpenFile[OpenFileFromRope[rope]]];
};
END.