PFSRopeFileImpl.mesa
Copyright Ó 1991, 1992 by Xerox Corporation. All rights reserved.
Michael Plass, November 25, 1991 3:30 pm PST
Doug Wyatt, October 22, 1991 11:18 am PDT
DIRECTORY
Basics USING [RawBytes, UnsafeBlock],
IO USING [PutR1, RIS, Value],
PFS USING [AccessOptions, AttributeSource, Close, CreateOptions, defaultCreateOptions, Error, FileInfo, FileType, Mutability, NameFormat, nullUniqueID, Open, OpenFile, OpenFileObject, Read, RopeFromPath, UniqueID],
PFSNames USING [Equal, PATH],
Rope USING [Substr, ROPE],
RopeFile USING [ByteSequenceObject, CreateByteSequenceObject, DeactivateResult, FromByteSequenceObject],
TiogaFileIO USING [GetParts, Parts];
PFSRopeFileImpl: CEDAR MONITOR LOCKS self USING self: ByteSequenceObject
IMPORTS PFS, RopeFile, IO, PFSNames, Rope, TiogaFileIO
EXPORTS PFS
~ BEGIN OPEN PFS;
PATH: TYPE ~ PFSNames.PATH;
ROPE: TYPE ~ Rope.ROPE;
ByteSequenceObject: TYPE ~ RopeFile.ByteSequenceObject;
DeactivateResult: TYPE ~ RopeFile.DeactivateResult;
Data: TYPE ~ REF DataRep;
DataRep: TYPE ~ RECORD [
fullFName: PATH,
uniqueID: UniqueID,
fileName: ROPE,
created: ROPE,
openFile: OpenFile
];
PFSDeactivate: ENTRY PROC [self: ByteSequenceObject, final: BOOL] RETURNS [result: DeactivateResult ¬ ok] ~ {
data: Data ~ NARROW[self.data];
openFile: OpenFile ¬ data.openFile;
IF openFile = NIL THEN RETURN [alreadyInactive];
data.openFile ¬ NIL;
PFS.Close[openFile ! PFS.Error => { result ¬ cant } ];
};
PFSEqual: ENTRY PROC [self, other: ByteSequenceObject] RETURNS [BOOL] ~ {
data: Data ~ NARROW[self.data];
WITH other.data SELECT FROM
otherData: Data => {
IF self.length # other.length THEN RETURN [FALSE];
IF data.uniqueID # otherData.uniqueID THEN RETURN [FALSE];
IF NOT PFSNames.Equal[data.fullFName, otherData.fullFName] THEN RETURN [FALSE];
Note this is a case-insensitive compare; however we've already matched length and uniqueID, so the case-insensitivity shouldn't be problem.
RETURN [TRUE]
};
ENDCASE;
RETURN [FALSE]
};
PFSDescribe: ENTRY PROC [self: ByteSequenceObject] RETURNS [fileName: ROPE, created: ROPE, open: BOOL] ~ {
data: Data ~ NARROW[self.data];
RETURN [fileName: data.fileName, created: data.created, open: data.openFile#NIL];
};
PFSMove: ENTRY UNSAFE PROC [self: ByteSequenceObject, block: Basics.UnsafeBlock, start: INT] RETURNS [charsMoved: INT ¬ 0] ~ UNCHECKED {
ENABLE UNWIND => NULL;
 FIXTHIS Turn PFS.Error into RopeFile.Error 
data: Data ~ NARROW[self.data];
IF data.openFile = NIL THEN {
data.openFile ¬ PFS.Open[name: data.fullFName, wantedUniqueID: data.uniqueID];
};
charsMoved ¬ PFS.Read[file: data.openFile, filePosition: start, nBytes: block.count,
to: block.base, toStart: block.startIndex];
};
RopeOpen: PUBLIC PROC [fileName: PFSNames.PATH, wantedUniqueID: UniqueID ¬ nullUniqueID, includeFormatting: BOOL ¬ FALSE, checkMutability: BOOL ¬ TRUE] RETURNS [rope: ROPE, fullFName: PATH, uniqueID: UniqueID] ~ {
length: INT;
mutability: Mutability;
data: Data ~ NEW[DataRep];
[fullFName: fullFName, attachedTo: data.fullFName, uniqueID: uniqueID, bytes: length, mutability: mutability] ¬ FileInfo[fileName, wantedUniqueID];
data.uniqueID ¬ uniqueID;
IF data.fullFName = NIL THEN data.fullFName ¬ fullFName;
data.fileName ¬ RopeFromPath[fullFName];
data.created ¬ IO.PutR1[[time[uniqueID.egmt.gmt]]];
rope ¬ RopeFile.FromByteSequenceObject[byteSequenceObject: RopeFile.CreateByteSequenceObject[length: length, data: data, equal: PFSEqual, deactivate: PFSDeactivate, describe: PFSDescribe, move: PFSMove], flatten: checkMutability AND mutability=mutable];
IF NOT includeFormatting THEN {
parts: TiogaFileIO.Parts ~ TiogaFileIO.GetParts[IO.RIS[rope]];
IF parts.isTioga THEN rope ¬ Rope.Substr[rope, parts.start1, parts.len1];
};
};
END.