<> <> <> <> <<>> <> <> <<>> 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.