FileReaderImpl.mesa
Copyright © 1985 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, March 3, 1985 4:38:43 pm PST
DIRECTORY
BasicTime,
FileOps,
FileReader,
FS,
Rope,
RopeIO,
IO,
RopeReader,
RefText;
FileReaderImpl: CEDAR PROGRAM
IMPORTS FS, Rope, RopeIO, RopeReader, RefText
EXPORTS FileReader
= BEGIN OPEN FileReader;
***** Operations for opening file
InterDoc:
PUBLIC
SIGNAL [doc:
ROPE] =
CODE;
-- raised by following procs
This is a silly hack to reduce the size of the return records to keep them SAFE.
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];
};
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] = {
Substr:
PROC [start, len:
INT]
RETURNS [Rope.
ROPE] = {
RETURN [RopeIO.FromFileC[openFile: file, start: start, len: len]];
};
interdoc: ROPE;
fileLen: INT;
[bytes: fileLen, created: createDate] ← FS.GetInfo[file];
[control,comment,text,interdoc,tiogaFile] ← DoOpen[fileLen,start,len,Substr];
IF interdoc#NIL THEN SIGNAL InterDoc[interdoc];
};
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 TEXT ← NEW[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[VAL[first]];
IF first.others
THEN {
Append[VAL[second]];
IF second.others
THEN {
Append[VAL[third]];
IF third.others
THEN {
Append[VAL[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] = {
Substr:
PROC [start,len:
INT]
RETURNS [
ROPE] = {
RETURN [Rope.Substr[rope,start,len]];
};
interdoc: ROPE;
[control,comment,text,interdoc,tiogaFile] ← DoOpen[Rope.Size[rope],start,len,Substr];
IF interdoc#NIL THEN SIGNAL InterDoc[interdoc];
};
**** 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];
[control,comment,text,tiogaFile] ← FromRope[rope,0,Rope.Size[rope]];
};
END.