netobjrt/src/ListPkl.m3


Copyright (C) 1994, Digital Equipment Corp.
ListPkl.m3
 Iterative List Pickle.Special to prevent small stacks from 
   overflowing on RefList.Ts of length >~ 25. 

UNSAFE MODULE ListPkl;

IMPORT RefList, Thread, Rd, Wr, Pickle;

PROCEDURE ListPklWrite (
    sp: Pickle.Special;
    r: REFANY; writer: Pickle.Writer)
    RAISES { Pickle.Error, Wr.Failure, Thread.Alerted } =
  VAR l: RefList.T := r; len := RefList.Length (l);
      isSubtype := TYPECODE(r) # TYPECODE(RefList.T);
  BEGIN
    Wr.PutChar (writer.wr, LOOPHOLE(isSubtype, CHAR));
    IF isSubtype THEN
      (* we don't know how to marshal subtypes of RefList.T *)
      Pickle.Special.write(sp, r, writer);
    ELSE
      writer.writeInt(len);
      FOR i := 1 TO len DO
        writer.write (l.head);
        l := l.tail;
      END;
      <* ASSERT l = NIL *>
    END;
  END ListPklWrite;

PROCEDURE ListPklRead (
    sp: Pickle.Special;
    reader: Pickle.Reader;
    id: Pickle.RefID) : REFANY
    RAISES { Pickle.Error, Rd.EndOfFile, Rd.Failure, Thread.Alerted } =
  VAR
    len: CARDINAL;
    res, tail: RefList.T;
    isSubtype := LOOPHOLE(Rd.GetChar(reader.rd), BOOLEAN);
  BEGIN
    IF isSubtype THEN
      (* the sender encountered a subtype of RefList.T *)
      res := Pickle.Special.read(sp, reader, id);
    ELSE
      len := reader.readInt();
      IF len < 0 THEN RAISE Pickle.Error("Pickle.Error: negative int"); END;
      res := NEW (RefList.T);
      tail := res;
      FOR i := 1 TO len - 1 DO
        tail.head := reader.read ();
        tail.tail := NEW (RefList.T);
        tail := tail.tail;
      END;
      tail.head := reader.read ();
      tail.tail := NIL;
    END;
    RETURN res;
  END ListPklRead;

BEGIN
  Pickle.RegisterSpecial (NEW (Pickle.Special, sc := TYPECODE (RefList.T),
    write := ListPklWrite,
    read  := ListPklRead));
END ListPkl.