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, September 18, 1986 3:47:42 pm PDT
DIRECTORY
BasicTime USING [GMT],
TiogaFile USING [commentHeaderId, controlHeaderId, controlTrailerId, endNode, endOfFile, endSize, FileId, 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, 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] = {
fh ← FS.Open[fileName];
[control, comment, text, tiogaFile, createDate] ← OpenC[fh, start, len];
};
OpenC: PUBLIC PROC [file: FS.OpenFile, start, len: INT] RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL, createDate: BasicTime.GMT] = {
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, tiogaFile] ← DoOpen[fileLen, start, len, Substr];
};
DoOpen: PROC [size, start, len: INT, Substr: PROC [start, len: INT] RETURNS [ROPE]]
RETURNS
[control, comment, text: RopeReader.Ref, tiogaFile: BOOL] = {
text ← RopeReader.Create[];
comment ← RopeReader.Create[];
control ← RopeReader.Create[];
tiogaFile ← TRUE;
{ -- for EXIT
trailerLen: INT ~ TiogaFile.endSize;
propsLen, textLen, fileLen, commentLen, controlLen: INT;
commentStart, controlStart, trailerStart: INT;
start ← MAX[0, MIN[start, size]];
len ← MAX[0, MIN[len, size-start]];
IF NOT len>trailerLen THEN GOTO FakeIt;
trailerStart ← start+len-trailerLen;
RopeReader.SetPosition[control, Substr[trailerStart, trailerLen]];
IF NOT ReadFileId[control, TiogaFile.controlTrailerId] THEN GOTO FakeIt;
IF NOT (propsLen ← ReadLen[control]) IN [0..len-trailerLen) THEN GOTO FakeIt;
IF NOT (textLen ← ReadLen[control]) IN [0..len-trailerLen) THEN GOTO FakeIt;
IF NOT (fileLen ← ReadLen[control])=len THEN GOTO FakeIt;
commentStart ← start+textLen;
RopeReader.SetPosition[comment, Substr[commentStart, trailerStart-commentStart]];
IF NOT ReadFileId[comment, TiogaFile.commentHeaderId] THEN GOTO FakeIt;
commentLen ← ReadLen[comment];
controlStart ← commentStart+commentLen;
RopeReader.SetPosition[control, Substr[controlStart, trailerStart-controlStart]];
IF NOT ReadFileId[control, TiogaFile.controlHeaderId] THEN GOTO FakeIt;
controlLen ← ReadLen[control];
IF NOT (textLen+commentLen+controlLen)=fileLen THEN GOTO FakeIt;
RopeReader.SetPosition[text, Substr[start, textLen]];
EXITS FakeIt => {
RopeReader.SetPosition[text, Substr[start, len]];
RopeReader.SetPosition[comment, NIL];
RopeReader.SetPosition[control, PhonyControl[len]];
tiogaFile ← FALSE;
};
};
};
ReadFileId: PROC [rdr: RopeReader.Ref, fileId: TiogaFile.FileId] RETURNS [BOOL] = {
FOR i: NAT IN [0..TiogaFile.fileIdSize) DO
IF RopeReader.Get[rdr]#fileId[i] THEN RETURN[FALSE];
ENDLOOP;
RETURN [TRUE];
};
ReadLen: PROC [rdr: RopeReader.Ref] RETURNS [INT] = {
len: PACKED ARRAY [0..4) OF CHAR;
len[0] ← RopeReader.Get[rdr];
len[1] ← RopeReader.Get[rdr];
len[2] ← RopeReader.Get[rdr];
len[3] ← RopeReader.Get[rdr];
RETURN [LOOPHOLE[len]];
};
PutInt: PROC [put: PROC [CHAR], val: INT] ~ {
intBytes: TiogaFile.IntBytes ~ LOOPHOLE[val];
boundsCheck: [0..0] ~ intBytes.unused;
first, second, fourth: TiogaFile.LengthByte;
third: TiogaFile.ThirdByte;
IF intBytes.fourth#0 THEN {
fourth.data ← intBytes.fourth;
first.others ← second.others ← third.others ← TRUE;
};
IF intBytes.thirdTop#0 OR intBytes.thirdBottom#0 THEN {
third.dataTop ← intBytes.thirdTop;
third.dataBottom ← intBytes.thirdBottom;
first.others ← second.others ← TRUE;
};
IF intBytes.second#0 THEN {
second.data ← intBytes.second; first.others ← TRUE;
};
first.data ← intBytes.first;
put[LOOPHOLE[first]];
IF first.others THEN {
put[LOOPHOLE[second]];
IF second.others THEN {
put[LOOPHOLE[third]];
IF third.others THEN {
put[LOOPHOLE[fourth]]
};
};
};
};
PhonyControl: PROC [len: INT] RETURNS [ROPE] = {
text: REF TEXTNEW[TEXT[16]];
Put: PROC [c: CHAR] ~ { text ← RefText.AppendChar[text, c] };
Put[TiogaFile.startNode]; -- start root node
Put[VAL[0]]; -- null type for root
Put[TiogaFile.terminalTextNode];
Put[VAL[0]]; -- null type for node
Put[TiogaFile.rope]; -- rope for node
PutInt[Put, len]; -- length of rope for node
Put[TiogaFile.endNode]; -- end of root
Put[TiogaFile.endOfFile];
RETURN[Rope.FromRefText[text]];
};
**** Read from rope instead of file
FromRope: PUBLIC PROC [rope: ROPE, start: INT ← 0, len: INTINT.LAST] RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL] = {
Substr: PROC [start, len: INT] RETURNS [ROPE] = {
RETURN [Rope.Substr[rope, start, len]];
};
size: INT ~ Rope.Size[rope];
start ← MAX[0, MIN[start, size]];
len ← MAX[0, MIN[len, size-start]];
[control, comment, text, tiogaFile] ← DoOpen[size, start, len, Substr];
};
**** Read from IO stream
FromStream: PUBLIC PROC [stream: IO.STREAM, len: INT] RETURNS [control, comment, text: RopeReader.Ref, tiogaFile: BOOL] = {
rope: ROPE ~ RopeIO.GetRope[stream, len];
RETURN FromRope[rope];
};
END.