FileReaderImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
written by Paxton. March 1981
Paxton. August 24, 1982 10:39 am
Last Edited by: Maxwell, January 5, 1983 1:07 pm
Russ Atkinson, July 26, 1983 5:41 pm
Last Edited by: Birrell, August 23, 1983 1:29 pm
Plass, March 29, 1985 4:54:11 pm PST
Doug Wyatt, August 28, 1986 4:22:53 pm PDT
DIRECTORY
BasicTime USING [GMT],
FileOps USING [commentHeaderId, controlHeaderId, controlTrailerId, endNode, endOfFile, endSize, fileIdSize, IntBytes, LengthByte, rope, startNode, terminalTextNode, ThirdByte],
FileReader USING [],
FS USING [GetInfo, Open, OpenFile],
IO USING [STREAM],
RefText USING [AppendChar],
Rope USING [FromRefText, ROPE, Size, Substr],
RopeIO USING [FromFileC, GetRope],
RopeReader USING [Create, EqSubstrs, Get, GetRope, Ref, SetPosition];
FileReaderImpl: CEDAR PROGRAM
IMPORTS FS, Rope, RopeIO, RopeReader, RefText
EXPORTS FileReader
= BEGIN OPEN FileReader;
ROPE: TYPE ~ Rope.ROPE;
***** Operations for opening file
Open: PUBLIC PROC [fileName: ROPE, start, len: INT]
RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL,
fh: FS.OpenFile, createDate: BasicTime.GMT, interdoc: ROPE] = {
fh ← FS.Open[fileName];
[control,comment,text,tiogaFile,createDate,interdoc] ← OpenC[fh,start,len];
};
IsInterDoc: PROC [textRope: ROPE] RETURNS [BOOL] = {
interdocHeader: ROPE = "{Interdoc/Interchange/";
RETURN [
RopeReader.EqSubstrs[textRope,interdocHeader,0,0,Rope.Size[interdocHeader]]] };
OpenC: PUBLIC PROC [file: FS.OpenFile, start, len: INT]
RETURNS [
control, comment, text: RopeReader.Ref, tiogaFile: BOOL,
createDate: BasicTime.GMT, interdoc: ROPE] = {
Substr: PROC [start, len: INT] RETURNS [Rope.ROPE] = {
RETURN [RopeIO.FromFileC[openFile: file, start: start, len: len]];
};
fileLen: INT;
[bytes: fileLen, created: createDate] ← FS.GetInfo[file];
[control,comment,text,interdoc,tiogaFile] ← DoOpen[fileLen,start,len,Substr];
};
DoOpen: PROC [totLen, start, len: INT, Substr: PROC [start,len: INT] RETURNS [ROPE]]
RETURNS [control, comment, text: RopeReader.Ref, interdoc: ROPE, tiogaFile: BOOL] = {
FakeFile: PROC = {
textRope: ROPE ← Substr[start,len];
IF IsInterDoc[textRope]
THEN interdoc ← textRope
ELSE {
tiogaFile ← FALSE;
RopeReader.SetPosition[text,textRope];
RopeReader.SetPosition[control,PhonyControl[len]]
};
};
{ -- for EXIT
commentStart,end,commentLen,controlLen,propsLen: INT;
endSize: NAT = FileOps.endSize;
endRope: Rope.ROPE;
tiogaFile ← TRUE;
start ← MAX[0,MIN[start,totLen]];
len ← MAX[0,MIN[len,totLen-start]];
end ← start+len;
text ← RopeReader.Create[];
comment ← RopeReader.Create[];
control ← RopeReader.Create[];
IF len <= endSize THEN GOTO FakeIt;
RopeReader.SetPosition[control,Substr[end-endSize,endSize]];
IF ~ReadControlTrailerId[control] THEN GOTO FakeIt;
IF (propsLen ← ReadLen[control]) NOT IN [0..len-endSize) THEN GOTO FakeIt;
IF (commentStart ← ReadLen[control]) NOT IN [0..len-endSize) THEN GOTO FakeIt;
IF ReadLen[control] # len THEN GOTO FakeIt;
endRope ← Substr[start+commentStart,len-commentStart]; -- comment and control
RopeReader.SetPosition[comment,endRope];
IF ~ReadCommentHeaderId[comment] THEN GOTO FakeIt;
commentLen ← ReadLen[comment];
RopeReader.SetPosition[control,endRope,commentLen];
IF ~ReadControlHeaderId[control] THEN GOTO FakeIt;
controlLen ← ReadLen[control];
IF commentStart+commentLen+controlLen # len THEN GOTO FakeIt;
RopeReader.SetPosition[text,Substr[start,commentStart]]
EXITS FakeIt => FakeFile[] }};
ReadControlHeaderId: PROC [control: RopeReader.Ref] RETURNS [BOOL] = {
FOR i:NAT IN [0..FileOps.fileIdSize) DO
IF RopeReader.Get[control] # FileOps.controlHeaderId[i] THEN RETURN[FALSE];
ENDLOOP;
RETURN [TRUE];
};
ReadCommentHeaderId: PROC [comment: RopeReader.Ref] RETURNS [BOOL] = {
FOR i:NAT IN [0..FileOps.fileIdSize) DO
IF RopeReader.Get[comment] # FileOps.commentHeaderId[i] THEN RETURN[FALSE];
ENDLOOP;
RETURN [TRUE];
};
ReadLen: PROC [rdr: RopeReader.Ref] RETURNS [INT] = {
start: PACKED ARRAY [0..3] OF CHAR;
start[0] ← RopeReader.Get[rdr];
start[1] ← RopeReader.Get[rdr];
start[2] ← RopeReader.Get[rdr];
start[3] ← RopeReader.Get[rdr];
RETURN [LOOPHOLE[start]];
};
ReadControlTrailerId: PROC [control: RopeReader.Ref] RETURNS [BOOL] = {
FOR i:NAT IN [0..FileOps.fileIdSize) DO
IF RopeReader.Get[control] # FileOps.controlTrailerId[i] THEN RETURN[FALSE];
ENDLOOP;
RETURN [TRUE];
};
PhonyControl: PROC [len: INT] RETURNS [r: ROPE] = {
first, second, fourth: FileOps.LengthByte;
third: FileOps.ThirdByte;
lenBytes: FileOps.IntBytes ← LOOPHOLE[len];
text: REF TEXTNEW[TEXT[16]];
Append: PROC [c: CHAR] ~ {
text ← RefText.AppendChar[text, c];
};
Append[FileOps.startNode]; -- start root node
Append[VAL[0]]; -- null type for root
Append[FileOps.terminalTextNode];
Append[VAL[0]]; -- null type for node
Append[FileOps.rope]; -- rope for node
length of rope for node
IF lenBytes.fourth # 0 THEN {
fourth.data ← lenBytes.fourth;
first.others ← second.others ← third.others ← TRUE;
};
IF lenBytes.thirdTop # 0 OR lenBytes.thirdBottom # 0 THEN {
third.dataTop ← lenBytes.thirdTop;
third.dataBottom ← lenBytes.thirdBottom;
first.others ← second.others ← TRUE;
};
IF lenBytes.second # 0 THEN {
second.data ← lenBytes.second; first.others ← TRUE;
};
first.data ← lenBytes.first;
Append[LOOPHOLE[first]];
IF first.others THEN {
Append[LOOPHOLE[second]];
IF second.others THEN {
Append[LOOPHOLE[third]];
IF third.others THEN {
Append[LOOPHOLE[fourth]] }}};
Append[FileOps.endNode]; -- end of root
Append[FileOps.endOfFile];
r ← Rope.FromRefText[text];
};
**** Read from rope instead of file
FromRope: PUBLIC PROC
[rope: ROPE, start, len: INT]
RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL, interdoc: ROPE] = {
Substr: PROC [start,len: INT] RETURNS [ROPE] = {
RETURN [Rope.Substr[rope,start,len]];
};
[control,comment,text,interdoc,tiogaFile] ← DoOpen[Rope.Size[rope],start,len,Substr];
};
**** Read from IO stream
FromStream: PUBLIC PROC [stream: IO.STREAM, len: INT]
RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL, interdoc: ROPE] = {
rope: ROPE ← RopeIO.GetRope[stream,len];
[control,comment,text,tiogaFile,interdoc] ← FromRope[rope,0,Rope.Size[rope]];
};
END.