MODULE DataQueues;
IMPORT NbrInt, DataErrors, DataIO;
CONST
VERSION* = 1;
TYPE
Node = POINTER TO RECORD
prev: Node;
obj: OBJECT;
END;
TYPE
Queue* = OBJECT
VAR len-: NbrInt.Integer;
first, last: Node;
PROCEDURE Read*( R: DataIO.Reader );
VAR i, length: NbrInt.Integer; p: OBJECT;
BEGIN {EXCLUSIVE}
R.Integer( length );
FOR i := 1 TO length DO R.Object( p ); Push( p ) END
END Read;
PROCEDURE Write*( W: DataIO.Writer );
VAR i: NbrInt.Integer; node: Node;
BEGIN
W.Integer( len ); node := last;
FOR i := 1 TO len DO W.Object( node.obj ); node := node.prev END
END Write;
PROCEDURE Pop*( VAR obj: OBJECT );
VAR next: Node;
BEGIN
IF len > 0 THEN
obj := last.obj; last.obj := NIL;
IF len > 1 THEN next := last; last := next.prev; next.prev := NIL ELSE first := NIL; last := NIL END;
NbrInt.Dec( len )
ELSE obj := NIL
END
END Pop;
PROCEDURE Push*( obj: OBJECT );
VAR node: Node;
BEGIN
NEW( node ); node.obj := obj;
IF first = NIL THEN first := node; last := node ELSE first.prev := node; first := node END;
NbrInt.Inc( len )
END Push;
END Queue;
PROCEDURE LoadObj( R: DataIO.Reader; VAR obj: OBJECT );
VAR version: SHORTINT; ver: NbrInt.Integer; new: Queue;
BEGIN
R.RawSInt( version );
IF version = -1 THEN
obj := NIL
ELSE
IF version = VERSION THEN NEW( new ); new.Read( R ); obj := new
ELSE
ver := version; DataErrors.IntError( ver, "Alien version number encountered." ); HALT( 1000 )
END
END
END LoadObj;
PROCEDURE StoreObj( W: DataIO.Writer; obj: OBJECT );
VAR old: Queue;
BEGIN
IF obj = NIL THEN W.RawSInt( -1 ) ELSE W.RawSInt( VERSION ); old := obj( Queue ); old.Write( W ) END
END StoreObj;
PROCEDURE Register;
VAR anInstanceOf: Queue;
BEGIN
NEW( anInstanceOf ); DataIO.PlugIn( anInstanceOf, LoadObj, StoreObj )
END Register;
PROCEDURE Load*( R: DataIO.Reader; VAR obj: Queue );
VAR ptr: OBJECT;
BEGIN
R.Object( ptr ); obj := ptr( Queue )
END Load;
PROCEDURE Store*( W: DataIO.Writer; obj: Queue );
BEGIN
W.Object( obj )
END Store;
BEGIN
Register
END DataQueues.