<<-- FileReaderImpl.Mesa>> <<-- written by Paxton. March 1981>> <> <> <<>> DIRECTORY CIFS, Directory, File, FileOps, FileReader, IO, PropertyTypes, Rope, RopeFrom, RopeIO, RopeReader, System, T2FileOps USING [controlTrailerId, DataPaddedFlag, DataUnpaddedFlag]; FileReaderImpl: CEDAR PROGRAM IMPORTS Rope, RopeFrom, RopeIO, RopeReader, CIFS, Directory EXPORTS FileReader = BEGIN <<-- ***** Operations for opening file>> Open: PUBLIC PROC [fileName: Rope.ROPE, start, len: FileReader.Offset, okToMapFile: BOOLEAN] RETURNS [reply:FileReader.Reply, fh: CIFS.OpenFile, createDate: System.GreenwichMeanTime]={ file: File.Capability _ CIFS.GetFC[fh _ CIFS.Open[fileName, CIFS.read]]; [reply, createDate] _ OpenC[file, start, len, okToMapFile] }; OpenC: PUBLIC PROC [file: File.Capability, start, len: FileReader.Offset, okToMapFile: BOOLEAN] RETURNS [reply:FileReader.Reply, createDate: System.GreenwichMeanTime] = TRUSTED { Substr: PROC [start, len: FileReader.Offset] RETURNS [Rope.ROPE] = TRUSTED { RETURN [RopeFrom.File[file, start, len, TRUE, fileLen, okToMapFile]] }; dummy: STRING _ [40]; fileLen: FileReader.Offset; [createDate: createDate, byteLength: fileLen] _ Directory.GetProps[file: file, name: dummy]; <> <> <> <> reply _ DoOpen[fileLen, start, len, Substr]; }; DoOpen: PROC [totLen, start, len: FileReader.Offset, Substr: PROC [start, len: FileReader.Offset] RETURNS [Rope.ROPE]] RETURNS [reply:FileReader.Reply] = { FakeFile: PROC = { <> textRope: Rope.ROPE _ Substr[start, len]; reply.fileType _ Simple; RopeReader.SetPosition[reply.text, textRope]; RopeReader.SetPosition[reply.control, PhonyControl[len]] }; { -- for EXIT commentStart, end, commentLen, controlLen, propsLen, propsStart: FileReader.Offset; endSize: NAT = FileOps.endSize; endRope: Rope.ROPE; pad:CARDINAL; reply _ NEW[FileReader.ReplyRec]; start _ MAX[0, MIN[start, totLen]]; len _ MAX[0, MIN[len, totLen-start]]; end _ start+len; reply.text _ RopeReader.Create[]; reply.comment _ RopeReader.Create[]; reply.control _ RopeReader.Create[]; IF len <= endSize THEN GOTO FakeIt; RopeReader.SetPosition[reply.control, Substr[end-endSize, endSize]]; -- 'control' reads the trailer [reply.fileType, pad] _ ReadControlTrailerId[reply.control]; SELECT reply.fileType FROM Tioga1 => { IF (propsLen _ ReadLen[reply.control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF (commentStart _ ReadLen[reply.control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF ReadLen[reply.control] # len THEN GOTO FakeIt; endRope _ Substr[start+commentStart, len-commentStart]; -- comment and control RopeReader.SetPosition[reply.comment, endRope]; IF ~ReadCommentHeaderId[reply.comment] THEN GOTO FakeIt; commentLen _ ReadLen[reply.comment]; RopeReader.SetPosition[reply.control, endRope, commentLen]; IF ~ReadControlHeaderId[reply.control] THEN GOTO FakeIt; controlLen _ ReadLen[reply.control]; IF commentStart+commentLen+controlLen # len THEN GOTO FakeIt; RopeReader.SetPosition[reply.text, Substr[start, commentStart]] }; Tioga2 => { <> IF (propsStart _ ReadLen[reply.control]) NOT IN [0..len-endSize] THEN GOTO FakeIt; <> <> IF (reply.controlStart _ ReadLen[reply.control]) NOT IN [0..len-endSize) THEN GOTO FakeIt; IF ReadLen[reply.control] # len THEN -- supposed length # actual length GOTO FakeIt; reply.controlStart _ start + reply.controlStart; RopeReader.SetPosition[reply.comment, Substr[reply.controlStart+propsStart, len-propsStart-endSize]]; -- comment reader will read props and symbol table reply.version _ ReadLen[reply.comment]; reply.text _ reply.control _ NIL; reply.textLen _ reply.controlStart - pad; reply.controlStart _ reply.controlStart + FileOps.fileIdSize; reply.controlLen _ propsStart - FileOps.fileIdSize; reply.textStart _ start; reply.fileRope _ Substr[0, len]; }; ENDCASE => GOTO FakeIt; EXITS FakeIt => FakeFile[] -- build a Fake Tioga1 file structure } }; ReadControlHeaderId: PROC [control: RopeReader.Ref] RETURNS [BOOLEAN] = { OPEN FileOps; FOR i:NAT IN [0..fileIdSize) DO IF RopeReader.Get[control] # controlHeaderId[i] THEN RETURN[FALSE]; ENDLOOP; RETURN [TRUE] }; ReadCommentHeaderId: PROC [comment: RopeReader.Ref] RETURNS [BOOLEAN] = { 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 [FileReader.Offset] = { OPEN RopeReader; start: PACKED ARRAY [0..3] OF CHARACTER; start[0] _ Get[rdr]; start[1] _ Get[rdr]; start[2] _ Get[rdr]; start[3] _ Get[rdr]; RETURN [LOOPHOLE[start]] }; ReadControlTrailerId: PROC [control: RopeReader.Ref] RETURNS [FileReader.FileType, CARDINAL] = { SELECT RopeReader.Get[control] FROM FileOps.controlTrailerId[0] => { FOR i:NAT IN [1..FileOps.fileIdSize) DO IF RopeReader.Get[control] # FileOps.controlTrailerId[i] THEN RETURN[Simple, 0]; ENDLOOP; RETURN [Tioga1, 0]; }; T2FileOps.controlTrailerId => { SELECT RopeReader.Get[control] FROM T2FileOps.DataPaddedFlag => RETURN [Tioga2, 1]; T2FileOps.DataUnpaddedFlag => RETURN [Tioga2, 0]; ENDCASE => RETURN[Simple, 0]; }; ENDCASE => RETURN[Simple, 0]; }; PhonyControl: PROC [len: FileReader.Offset] RETURNS [r: Rope.ROPE] = { OPEN FileOps; first, second, fourth: LengthByte; third: ThirdByte; lenBytes: IntBytes _ LOOPHOLE[len]; r _ RopeFrom.Character[startNode]; -- start root node r _ RopeFrom.FlatAppendByte[r, 0]; -- null type for root r _ RopeFrom.FlatAppendChar[r, terminalTextNode]; r _ RopeFrom.FlatAppendByte[r, 0]; -- null type for node r _ RopeFrom.FlatAppendChar[r, 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; r _ RopeFrom.FlatAppendByte[r, first]; IF first.others THEN { r _ RopeFrom.FlatAppendByte[r, second]; IF second.others THEN { r _ RopeFrom.FlatAppendByte[r, third]; IF third.others THEN { r _ RopeFrom.FlatAppendByte[r, fourth] }}}; r _ RopeFrom.FlatAppendChar[r, endNode]; -- end of root r _ RopeFrom.FlatAppendChar[r, endOfFile]}; <<-- **** Read from rope instead of file>> FromRope: PUBLIC PROC [rope: Rope.ROPE, start, len: FileReader.Offset] RETURNS [reply:FileReader.Reply] = { Substr: PROC [start, len: FileReader.Offset] RETURNS [Rope.ROPE] = { RETURN [Rope.Substr[rope, start, len]] }; reply _ DoOpen[Rope.Size[rope], start, len, Substr]; }; <<-- **** Read from IO stream >> FromStream: PUBLIC PROC [stream: IO.Handle, len: FileReader.Offset] RETURNS [reply:FileReader.Reply] = { rope: Rope.ROPE _ RopeIO.GetRope[stream, len]; reply _ FromRope[rope, 0, Rope.Size[rope]] }; <<-- **** Miscellaneous>> Start: PUBLIC PROC = { }; END. <> <> <> <> <> <<>> <> <> <> <> <> <> <> <> <> <> <<>>