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