-- PGStreams.Mesa
-- written by Paxton. February 1981
-- last written by Paxton. February 20, 1981 2:46 PM

-- Uses FileByteStream to create special streams for Put/Get.

DIRECTORY
FileOps: FROM "TiogaFileOps" USING [Byte],
FileByteStream: FROM "TiogaFBS" USING [
Transaction, CreateOptions, AccessOptions, Handle],
InlineDefs: FROM "InlineDefs" USING [LowHalf],
Rope: FROM "Rope" USING [Ref],
RopeReader: FROM "RopeReader" USING [Ref];

PGStreams: DEFINITIONS
IMPORTS InlineDefs =

BEGIN

Card: TYPE = LONG CARDINAL;

PGStreamMode: TYPE = {read, write};
PGStream: TYPE = REF PGStreamBody;
PGStreamBody: PRIVATE TYPE = RECORD [
loc: NAT ← 0, -- index in block of next character to read or write
after: NAT ← 0, -- index beyond last character to read or write
block: Block, -- block of chars for current read/write
blockSeq: REF BlockSeq, -- sequence of text blocks
blockNum: NAT ← 0, -- index in blockSeq of next block
file: FileByteStream.Handle,
reader: RopeReader.Ref, -- for use in moving characters from ropes
pgm: PGM, -- ref to monitored record for reading/writing
process: PROCESS, -- process doing reads/writes with pgm
other: PGStream, -- text and control streams point to each other
mode: PGStreamMode, -- read/write
kind: OfBlock -- text/control
];

OfBlock: TYPE = {control, text};
Block: TYPE = REF BlockBody;
BlockBody: TYPE = TEXT--[blockSize]--;
blockSize: NAT = 1024;
BlockSeq: TYPE = RECORD[SEQUENCE length:NAT OF Block];

OpenPGStreams: PROC [
filename: Rope.Ref, transaction: FileByteStream.Transaction ← NIL,
createOptions: FileByteStream.CreateOptions ← none,
accessOptions: FileByteStream.AccessOptions ← write]
RETURNS [control, text: PGStream];

ClosePGStreams: PROC [str: PGStream];

ReadChar: PROC [str: PGStream] RETURNS [char: CHARACTER] = INLINE
BEGIN
loc: CARDINAL;
IF (loc←str.loc) >= str.after THEN
RETURN[ReadCharSupport[str]];
str.loc ← loc+1;
RETURN[str.block[loc]];
END;

ReadCharSupport: PRIVATE PROC [str: PGStream]
RETURNS [char: CHARACTER];

SkipChar: PROC [str: PGStream] = INLINE
BEGIN
loc: CARDINAL;
IF (loc←str.loc) >= str.after THEN
RETURN--[SkipCharSupport[str]]--;
str.loc ← loc+1;
END;

SkipCharSupport: PRIVATE PROC [str: PGStream];

ReadByte: PROC [str: PGStream] RETURNS [[0..255]] = INLINE {
RETURN[LOOPHOLE[ReadChar[str], TiogaFileOps.Byte]]};

ReadWord: PROC [str: PGStream] RETURNS [CARDINAL];

ReadDoubleWord: PROC [str: PGStream] RETURNS [Card];

MakeRope: PROC [len: Card, str: PGStream] RETURNS [rope: Rope.Ref];

WriteChar: PROC [char: CHARACTER, str: PGStream] = INLINE
BEGIN
loc: CARDINAL;
IF (loc←str.loc) >= str.after THEN
{ WriteCharSupport[char, str]; RETURN };
str.loc ← loc+1;
str.block[loc] ← char;
END;

WriteCharSupport: PRIVATE PROC [char: CHARACTER, str: PGStream];

WriteByte: PROC [byte: [0..255], str: PGStream] = INLINE {
WriteChar[LOOPHOLE[byte], str]};

WriteWord: PROC [wd: CARDINAL, str: PGStream];

WriteDoubleWord: PROC [dwd: Card, str: PGStream];

WriteRope: PROC [rope: Rope.Ref, str: PGStream];

PutRope: PROC [
rope: Rope.Ref, size: Card, str1, str2: PGStream] = INLINE {
WriteByte[LOOPHOLE[InlineDefs.LowHalf[size]], str1];
WriteRope[rope, str2]};

PutLongRope: PROC [
rope: Rope.Ref, size: Card, str1, str2: PGStream] = INLINE {
WriteWord[InlineDefs.LowHalf[size], str1];
WriteRope[rope, str2]};

PutVeryLongRope: PROC [
rope: Rope.Ref, size: Card, str1, str2: PGStream] = INLINE {
WriteDoubleWord[size, str1];
WriteRope[rope, str2]};

-- following implemented by TiogaPGMonitorImpl

PGM: TYPE = REF PGMBody;
PGMBody: TYPE; -- the monitored record

CreatePGM: PROC [PGStreamMode] RETURNS [PGM];
-- creates monitored record for use in put/get

AddToControlList: PROC [pgm: PGM, block: Block];
-- adds block to end of control read list

GetFromControlList: PROC [pgm: PGM] RETURNS [Block];
-- removes first block from control read list
-- returns NIL when certain that nothing more to read
-- i.e., after there has been a call on ControlReadsDone

ControlReadsDone: PROC [pgm: PGM];
-- promises that there will be no more calls on AddToControlList

TextReadsDone: PROC [pgm: PGM];
-- informs world that have finished reading text

WriteTextBlock: PROC [pgm: PGM, block: Block];
--puts text block at end of write list

WriteControlBlock: PROC [pgm: PGM, block: Block];
--puts control block at end of deferred list

GetFromWriteList: PROC [pgm: PGM] RETURNS [Block];
-- call this to get a block to write
-- returns NIL when certain that nothing more to write
-- i.e., after there has been a call on WritesDone

WritesDone: PROC [pgm: PGM];
-- promises that there will be no more calls on AddToWriteList


END.

LOG
added formals ids to PROC definitions. Pier, 12/7/80
added inlines for ReadChar/WriteChar. Paxton, 2/2/81
changed to use TiogaFBS. Pier, 2/11/81
fixed up to compile properly. Pier 2/20/81