Last modified on Mon Mar 21 13:15:19 PST 1994 by kalsow modified on Fri Jun 18 11:34:44 PDT 1993 by wobber modified on Thu May 20 15:22:41 PDT 1993 by swart modified on Mon Apr 26 17:25:44 PDT 1993 by mcjones modified on Thu Jul 11 20:58:41 1991 by muller
MODULE; IMPORT EventWr, EventWrF, RdClass, RdCopy, Rd, Wr, Thread, WrClass; EventRd
IMPORT IO, Fmt;
REVEAL T = Public BRANDED "EventRd.T" OBJECT cur_buf : INTEGER := 0; (* index of the active buffer *) max_len : INTEGER := 0; (* largest value of rd.cur possible *) n_buffers : INTEGER := 0; (* # of allocated buffers *) buffers : BufferList := NIL;(* overflow array *) wr : EventWr.T := NIL;(* The EventWr.T use to init this. *) OVERRIDES seek := Seek; length := Length; init := Init; END; TYPE BufferList = EventWrF.BufferList; CONST BufferSize = EventWrF.BufferSize; PROCEDUREInit (rd: T; wr: EventWr.T): T = (* VAR len := Wr.Length (wr); *) <*FATAL Wr.Failure, Thread.Alerted *> BEGIN (* IF (rd.buff = NIL) OR (len > NUMBER (rd.buff^)) THEN rd.buff := NEW(REF ARRAY OF CHAR, len); END; *) (* Copy the stuff from the writer. *) rd.wr := wr; rd.extMu := NEW(Thread.Mutex); IF wr # NIL THEN (* Make sure it's flushed. *) Wr.Flush(wr); rd.max_len := wr.max_len; rd.n_buffers := wr.n_buffers; rd.buffers := wr.buffers; (* Steal the buffers so that if the writer is init'd again, it gets new buffers. *) wr.buffers := NIL; wr.buff := NIL; ELSE IF rd.buffers = NIL THEN rd.buffers := NEW(BufferList, 32); FOR i := FIRST (rd.buffers^) TO LAST (rd.buffers^) DO rd.buffers[i] := NIL; END; END; END; rd.st := 0; rd.cur := 0; rd.closed := FALSE; rd.seekable := TRUE; rd.intermittent := FALSE; GotoBuffer(rd, 0); RETURN rd; END Init; PROCEDUREToWr (rd: T) : EventWr.T = VAR wr: EventWr.T; BEGIN IF rd = NIL OR rd.wr = NIL THEN RETURN NIL END; wr := rd.wr; (* Reinitialize the writer. *) wr.buffers := rd.buffers; EVAL wr.init(); (* Drop references and return the wr. *) rd.wr := NIL; rd.buffers := NIL; rd.buff := NIL; RETURN wr; END ToWr; PROCEDUREGotoBuffer (rd: T; n: INTEGER) = VAR buf := n DIV BufferSize; BEGIN <* ASSERT buf <= LAST (rd.buffers^) *> rd.cur_buf := buf; rd.buff := rd.buffers [buf]; rd.lo := buf * BufferSize; rd.hi := MIN(rd.lo + BufferSize, rd.max_len); END GotoBuffer; PROCEDURENew (t: EventWr.T): T = BEGIN RETURN NEW(T).init(t); END New; PROCEDURELength (rd: T): INTEGER RAISES {} = BEGIN RETURN rd.max_len; END Length; PROCEDURESeek (rd: T; pos: CARDINAL; <*UNUSED*> dontBlock: BOOLEAN): RdClass.SeekResult = BEGIN (* IO.Put(Fmt.F("EventRd.Seek(%s) => max=%s\n", Fmt.Unsigned(pos, 10), Fmt.Int(rd.max_len))); *) IF pos >= rd.max_len THEN rd.cur := rd.max_len; GotoBuffer(rd, rd.cur); (* IO.Put(Fmt.F("EventRd.Seek(%s) => set cur=%s and return Eof\n", Fmt.Int(pos), Fmt.Int(rd.cur))); *) RETURN RdClass.SeekResult.Eof; ELSE IF (pos < rd.lo) OR (rd.hi <= pos) THEN GotoBuffer (rd, pos) END; rd.cur := pos; (* IO.Put(Fmt.F("EventRd.Seek(%s) => set cur=%s and return Ready\n", Fmt.Unsigned(pos, 10), Fmt.Int(rd.cur))); *) RETURN RdClass.SeekResult.Ready; END; END Seek; PROCEDUREFromRd (rd: Rd.T; erd: T) : T RAISES {Rd.Failure, Thread.Alerted} = VAR wr: EventWr.T := ToWr(erd); num : INTEGER; <*FATAL Wr.Failure *> BEGIN IF wr = NIL THEN wr := NEW(EventWr.T).init(); END; num := RdCopy.ToWriter(rd, wr); (* IO.Put("Created EventRd from Read of " & Fmt.Int(num) & " bytes\n"); *) IF erd = NIL THEN erd := NEW(T); END; RETURN erd.init(wr); END FromRd; BEGIN END EventRd.