-- CGBandStreamImpl.mesa Cedar 3.4
-- Last changed by Ken Pier, October 8, 1982 3:32 pm

DIRECTORY
CGBandStream,
ConvertUnsafe USING [ToRope],
UnsafeStorage USING [GetSystemUZone],
Rope USING[ROPE],
Runtime USING[CallDebugger],
IO USING [UnsafeBlock, UnsafePutBlock, UnsafeGetBlock, Close,
Signal, Error, PutFR, rope, card, SetIndex, GetIndex],
CGStorage USING [pZone],
Environment USING[wordsPerPage],
Inline USING [LongCOPY, LowHalf],
FileIO USING [AccessOptions, Open];

CGBandStreamImpl: PROGRAM
IMPORTS Runtime, IO, FileIO, ConvertUnsafe, Inline, CGStorage, UnsafeStorage
EXPORTS CGBandStream = {
OPEN IO, FIO: FileIO, CGBandStream;

uz: UNCOUNTED ZONE ← UnsafeStorage.GetSystemUZone[];
pZone: ZONE = CGStorage.pZone;
keepPagesOnClose: CARDINAL = 0;

--OpenBand takes a prefix string (usually PBAND.) and an index (i). Opens a
--FileIO stream on file PBAND.i, returning a handle

OpenBand: PUBLIC PROC[name: BandPrefix, index: BandIndex, access: FIO.AccessOptions ← read]
RETURNS [bStream: BandStreamHandle] = {

rFile: Rope.ROPE;
rFile ← IF index#LAST[BandIndex] THEN
IO.PutFR[ , IO.rope[ConvertUnsafe.ToRope[name]], IO.card[index]]
ELSE IO.PutFR[ , IO.rope[ConvertUnsafe.ToRope[name]]];
bStream ← FIO.Open[fileName: rFile, accessOptions: access,
   closeOptions: keepPagesOnClose ! IO.Error, IO.Signal =>
     TRUSTED {Runtime.CallDebugger["BSOpenFailed"L]}];
};--OpenBand

PutBand: PUBLIC PROC[band: BandStreamHandle, from: LONG POINTER, words: LONG INTEGER] = {
--send words to the bandstream

bytes: LONG INTEGER ← words*2;
uBlock: IO.UnsafeBlock;
uBlock ← [base: from, startIndex: 0, stopIndexPlusOne: bytes];
IO.UnsafePutBlock[band, uBlock];
};--PutBand

StartGetBand: PUBLIC PROC[band: BandStreamHandle] = {
IO.SetIndex[band, 0];
wordsLeft ← 0; bRef ← bStart;
};--StartBand

GetBand: PUBLIC PROC[band: BandStreamHandle, to: LONG POINTER, words: LONG INTEGER] RETURNS [LONG INTEGER] = {
--get the incoming block and deliver to client
nWords, wordsRead, temp: LONG INTEGER ← 0;
cWords: CARDINAL ← 0;
uBlock: IO.UnsafeBlock;
DO
nWords ← IF words <= wordsLeft THEN words ELSE wordsLeft; --LongMIN[words, wordsLeft]
cWords ← Inline.LowHalf[nWords];
Inline.LongCOPY[from: bRef, nwords: cWords, to: to];
wordsRead ← wordsRead+nWords; temp ← words-wordsLeft;
IF nWords=words THEN {--buffer had all the words
wordsLeft ← -temp; --wordsLeft-words
bRef ← bRef+words; IF (bEnd - bRef) < 0 THEN ERROR; EXIT;
};
--buffer empty and more to COPY. temp contains remaining word count
bRef ← bStart; words ← temp; to ← to+wordsLeft;
uBlock ← [base: LOOPHOLE[bStart], startIndex: 0, stopIndexPlusOne: bufferBytes];
wordsLeft ← (IO.UnsafeGetBlock[band, uBlock])/2; IF wordsLeft=0 THEN EXIT;
ENDLOOP;
RETURN[wordsRead];
};--GetBand

SkipBand: PUBLIC PROC [band: BandStreamHandle, words: LONG INTEGER] RETURNS [wordsSkipped: LONG INTEGER] = {
temp: LONG INTEGER;
temp ← words-wordsLeft;
IF temp <= 0 THEN {--buffer had all the words
wordsLeft ← -temp; --wordsLeft-words
bRef ← bRef+words; IF (bEnd - bRef) < 0 THEN ERROR; wordsSkipped ← words; RETURN};

--buffer empty and more to SKIP. temp contains skip count
--skip ahead in stream:
IO.SetIndex[band, IO.GetIndex[band]+temp*2];
wordsSkipped ← words;
wordsLeft ← 0; bRef ← bStart;
};--SkipBand

CloseBand: PUBLIC PROC[b: BandStreamHandle] = {
IO.Close[b ! IO.Error, IO.Signal =>
TRUSTED {Runtime.CallDebugger["BSCloseFailed"L]}];
};--CloseBand

SetBufferPages: PUBLIC PROC[bP: CARDINAL ← 1] = {

IF bP = bufferPages THEN RETURN;
bufferPages ← bP;
bufferWords ← bP*Environment.wordsPerPage;
bufferBytes ← bufferWords*2;
IF bStart#NIL THEN uz.FREE[@bStart];
bStart ← uz.NEW[Buffer[bufferWords]];
bEnd ← bStart+bufferWords;
};--SetBufferPages


--global storage

bufferPages: PUBLIC CARDINAL ← 1;
bufferWords: CARDINAL ← bufferPages*Environment.wordsPerPage;
bufferBytes: CARDINAL ← bufferWords*2;
wordsLeft: LONG INTEGER ← 0;--remaining valid words in Get buffer
Buffer: TYPE = RECORD[SEQUENCE COMPUTED CARDINAL OF WORD];
BufferP: TYPE = LONG POINTER TO Buffer;
bRef, bEnd: BufferP ← NIL;
bStart: BufferP ← uz.NEW[Buffer[bufferWords]];
bEnd ← bStart+bufferWords;



}.--CGBandStreamImpl



LOG

converted to IOStreams, 10-Dec-81 10:50:15, by Pier
changed PutBand, GetBand from Band to BandStreamHandle, 15-Jan-82, Pier
reformatted, 19-JAN-82
converted to FileIOStreams, 2/2/82
added large buffer stuff and SkipBand, 2/23/82
added SetBufferPages, 2/28/82
added UNCOUNTED ZONE, 3/3/82
changed Put and Get to use LONG POINTERS instead of REFs, 30-Mar-82
swapped UnsafeStorage for Heap, 5/3/82
convert to Cedar 3.2, June 29, 1982
added option to ignore BandIndex in OpenBand, 7/13/82