Прошу:
Код:
MODULE назовите-как-хотите;
IMPORT S := SYSTEM, Kernel, Files;
TYPE
Bytes = ARRAY [untagged] 1000000000 OF BYTE;
PROCEDURE SizeOf* (IN rec: ANYREC): INTEGER;
VAR type: Kernel.Type;
BEGIN
type := S.VAL(Kernel.Type, S.TYP(rec));
RETURN type.size
END SizeOf;
PROCEDURE RecWithoutPtrFields* (IN rec: ANYREC): BOOLEAN;
VAR t: Kernel.Type;
BEGIN
t := S.VAL(Kernel.Type, S.TYP(rec));
RETURN t.ptroffs[0] < 0
END RecWithoutPtrFields;
PROCEDURE RecToBytes* (IN rec: ANYREC; VAR bytes: ARRAY OF BYTE; VAR pos: INTEGER);
VAR t: Kernel.Type;
BEGIN
t := S.VAL(Kernel.Type, S.TYP(rec));
ASSERT(t.ptroffs[0] < 0, 20);
ASSERT(pos + t.size <= LEN(bytes), 21);
IF Kernel.littleEndian THEN
S.MOVE(S.ADR(rec), S.ADR(bytes) + pos, t.size);
INC(pos, t.size)
ELSE
HALT(126)
END
END RecToBytes;
PROCEDURE RecFromBytes* (VAR rec: ANYREC; IN bytes: ARRAY OF BYTE; VAR pos: INTEGER);
VAR t: Kernel.Type;
BEGIN
t := S.VAL(Kernel.Type, S.TYP(rec));
ASSERT(t.ptroffs[0] < 0, 20);
ASSERT(pos + t.size <= LEN(bytes), 21);
IF Kernel.littleEndian THEN
S.MOVE(S.ADR(bytes) + pos, S.ADR(rec), t.size);
INC(pos, t.size)
ELSE
HALT(126)
END
END RecFromBytes;
PROCEDURE RecToFile* (IN rec: ANYREC; wr: Files.Writer);
VAR t: Kernel.Type;
BEGIN
t := S.VAL(Kernel.Type, S.TYP(rec));
ASSERT(t.ptroffs[0] < 0, 20);
IF Kernel.littleEndian THEN
wr.WriteBytes(S.VAL(Bytes, rec), 0, t.size)
ELSE
HALT(126)
END
END RecToFile;
PROCEDURE RecFromFile* (VAR rec: ANYREC; rd: Files.Reader);
VAR t: Kernel.Type;
BEGIN
t := S.VAL(Kernel.Type, S.TYP(rec));
ASSERT(t.ptroffs[0] < 0, 20);
IF Kernel.littleEndian THEN
rd.ReadBytes(S.VAL(Bytes, rec), 0, t.size)
ELSE
HALT(126)
END
END RecFromFile;
PROCEDURE New* (IN sameType: ANYREC): ANYPTR;
BEGIN
RETURN S.VAL(ANYPTR, Kernel.NewRec(S.TYP(sameType)))
END New;
PROCEDURE CopyBase* (IN src: ANYREC; VAR dest: ANYREC);
(* Берёт "общий знаменатель" двух записей и копирует из src в dest *)
VAR ts, td: Kernel.Type;
i: INTEGER;
BEGIN
ASSERT(S.ADR(src) # S.ADR(dest), 20);
ts := S.VAL(Kernel.Type, S.TYP(src));
td := S.VAL(Kernel.Type, S.TYP(dest));
i := 0;
WHILE (ts.base[i] # NIL) & (ts.base[i] = td.base[i]) DO
INC(i)
END;
IF i > 0 THEN
S.MOVE(S.ADR(src), S.ADR(dest), ts.base[i-1].size)
END
END CopyBase;