(* Copyright (C) 1990, Digital Equipment Corporation. *) (* All rights reserved. *) (* See the file COPYRIGHT for a full description. *) (* Last modified on Thu Aug 29 19:59:53 1991 by kalsow *) (* modified on Mon Oct 22 11:13:48 PDT 1990 by crelier *) INTERFACE Pkl; (* Type-safe binary storage for linked data structures *) IMPORT Rd, Wr, Thread; EXCEPTION Error(Code); PROCEDURE Write(r: REFANY; wr: Wr.T; lg2maxobjs := 14) RAISES {Wr.Failure, Thread.Alerted, Error}; (* Trace the data structure reachable via traced references from r, convert it into a sequence of bytes (called a pickle), and write the pickle to wr. Shared or circular substructures will be preserved. Any untraced references will be pickled as NIL. Procedures will be preserved. Methods will be restored to the default suite. The structure r itself is not changed. The writer wr must be seekable. Additional control is provided by registering procedures as described below. lg2maxobjs is the logarithm in basis 2 of the expected maximum number of objects to be pickled. It is used as a hint for the size of locally allocated structures. If more than 2^lg2maxobjs objects are present, then resizing of these structures occurs without raising any error. *) PROCEDURE Read(rd: Rd.T): REFANY RAISES {Rd.Failure, Thread.Alerted, Error}; (* Read a pickle from rd, reconstruct a copy of the pickled data structure, and return it. *) TYPE ConvertProc = PROCEDURE(r: REFANY); PROCEDURE RegisterConvertProcs( tc: INTEGER; wrproc: ConvertProc; rdproc: ConvertProc); (* Register wrproc and rdproc as the write and read conversion procedures for the type with code tc. It is a checked error to call this more than once for the same type, unless wrproc and rdproc are the same as they were on the previous calls (in which case it is a noop). Whenever Pkl.Write traces a reference r, if a write conversion procedure has been registered for r's type or any of its supertypes, then r is copied, the conversion procedures for r's type and its supertypes are applied to the copy in supertype-to-subtype order, and then tracing continues using the copy in place of the original reference. Whenever Pkl.Read reconstructs a reference r, then the read conversion procedures for r's type and its supertypes are applied to r in supertype-to-subtype order. *) TYPE WriteBytesProc = PROCEDURE(r: REFANY): TEXT; ReadBytesProc = PROCEDURE(READONLY bytes: ARRAY OF CHAR): REFANY; PROCEDURE RegisterBytesProcs( tc: INTEGER; wrproc: WriteBytesProc; rdproc: ReadBytesProc); (* Register wrproc and rdproc as the write and read conversion procedures for the type with code tc. Whenever Pkl.Write traces a reference r, if r's type has a WriteBytes procedure p, then p(r) is called, the resulting text is written into the pickle, and r is otherwise ignored (it is not traced). Whenever Pkl.Read encounters a sequence of bytes in a pickle that were written by a WriteBytes special for type t, then the ReadBytes special for type t is applied to those bytes and the result is included in the data structure in place of the original reference r. In Pkl.Write, convert procs are applied before WriteBytes procs. In Pkl.Read, ReadBytes procs are applied before convert procs. *) TYPE Code = { BadVersion, (* raised by Pkl.Read if the version numbers in the file and in the reading program are different *) UnknownType, (* raised by Pkl.Read if the pickle contains some type that is not present in the reading program. *) UnknownProc, (* raised by Pkl.Read if the pickle contains some procedure that is not present in the reading program. *) NoReadBytesProc, (* raised by Pkl.Read if the pickle contains a sequence of bytes written by a WriteBytesProc registered for type T, but there is no ReadBytesProc registered for T in the reading program. *) WrongType, (* raised by Pkl.Read if a ReadBytesProc registered for type T returns a result that is not a member of type T. *) Unseekable (* raised by Pkl.Write if given an unseekable writer. *) }; END Pkl.