mirror of
https://github.com/vishapoberon/compiler.git
synced 2026-04-06 18:02:25 +00:00
546 lines
16 KiB
Modula-2
546 lines
16 KiB
Modula-2
(* Ulm's Oberon Library
|
|
Copyright (C) 1989-1994 by University of Ulm, SAI, D-89069 Ulm, Germany
|
|
----------------------------------------------------------------------------
|
|
Ulm's Oberon Library is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either version
|
|
2 of the License, or (at your option) any later version.
|
|
|
|
Ulm's Oberon Library is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
|
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
----------------------------------------------------------------------------
|
|
E-mail contact: oberon@mathematik.uni-ulm.de
|
|
----------------------------------------------------------------------------
|
|
$Id: NetIO.om,v 1.4 2004/05/21 15:19:03 borchert Exp $
|
|
----------------------------------------------------------------------------
|
|
$Log: NetIO.om,v $
|
|
Revision 1.4 2004/05/21 15:19:03 borchert
|
|
performance improvements:
|
|
- ReadConstStringD prefers Streams.ReadPart and ConstStrings.CreateD,
|
|
if possible
|
|
(based on code by Christian Ehrhardt)
|
|
- WriteConstString uses Streams.Copy instead of a loop that uses
|
|
Streams.ReadByte and Streams.WriteByte
|
|
|
|
Revision 1.3 1995/03/17 16:28:20 borchert
|
|
- SizeOf stuff removed
|
|
- support of const strings added
|
|
- support of Forwarders added
|
|
|
|
Revision 1.2 1994/07/18 14:18:37 borchert
|
|
unused variables of WriteString (ch + index) removed
|
|
|
|
Revision 1.1 1994/02/22 20:08:43 borchert
|
|
Initial revision
|
|
|
|
----------------------------------------------------------------------------
|
|
AFB 6/93
|
|
----------------------------------------------------------------------------
|
|
*)
|
|
|
|
MODULE ulmNetIO;
|
|
|
|
(* abstraction for the exchange of Oberon base types which
|
|
are components of persistent data structures
|
|
*)
|
|
|
|
IMPORT ConstStrings := ulmConstStrings, Disciplines := ulmDisciplines, Forwarders := ulmForwarders, Streams := ulmStreams, Strings := ulmStrings,
|
|
SYS := SYSTEM, Types := ulmTypes;
|
|
|
|
TYPE
|
|
Byte* = Types.Byte;
|
|
|
|
TYPE
|
|
ReadByteProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR byte: Byte) : BOOLEAN;
|
|
ReadCharProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR char: CHAR) : BOOLEAN;
|
|
ReadBooleanProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR boolean: BOOLEAN) : BOOLEAN;
|
|
ReadShortIntProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR shortint: SHORTINT) : BOOLEAN;
|
|
ReadIntegerProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR integer: INTEGER) : BOOLEAN;
|
|
ReadLongIntProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR longint: LONGINT) : BOOLEAN;
|
|
ReadRealProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR real: REAL) : BOOLEAN;
|
|
ReadLongRealProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR longreal: LONGREAL) : BOOLEAN;
|
|
ReadSetProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR set: SET) : BOOLEAN;
|
|
ReadStringProc* =
|
|
PROCEDURE (s: Streams.Stream; VAR string: ARRAY OF CHAR) : BOOLEAN;
|
|
ReadConstStringProc* =
|
|
PROCEDURE (s: Streams.Stream; domain: ConstStrings.Domain;
|
|
VAR string: ConstStrings.String) : BOOLEAN;
|
|
|
|
WriteByteProc* =
|
|
PROCEDURE (s: Streams.Stream; byte: Byte) : BOOLEAN;
|
|
WriteCharProc* =
|
|
PROCEDURE (s: Streams.Stream; char: CHAR) : BOOLEAN;
|
|
WriteBooleanProc* =
|
|
PROCEDURE (s: Streams.Stream; boolean: BOOLEAN) : BOOLEAN;
|
|
WriteShortIntProc* =
|
|
PROCEDURE (s: Streams.Stream; shortint: SHORTINT) : BOOLEAN;
|
|
WriteIntegerProc* =
|
|
PROCEDURE (s: Streams.Stream; integer: INTEGER) : BOOLEAN;
|
|
WriteLongIntProc* =
|
|
PROCEDURE (s: Streams.Stream; longint: LONGINT) : BOOLEAN;
|
|
WriteRealProc* =
|
|
PROCEDURE (s: Streams.Stream; real: REAL) : BOOLEAN;
|
|
WriteLongRealProc* =
|
|
PROCEDURE (s: Streams.Stream; longreal: LONGREAL) : BOOLEAN;
|
|
WriteSetProc* =
|
|
PROCEDURE (s: Streams.Stream; set: SET) : BOOLEAN;
|
|
WriteStringProc* =
|
|
PROCEDURE (s: Streams.Stream; string: ARRAY OF CHAR) : BOOLEAN;
|
|
WriteConstStringProc* =
|
|
PROCEDURE (s: Streams.Stream;
|
|
string: ConstStrings.String) : BOOLEAN;
|
|
|
|
Interface* = POINTER TO InterfaceRec;
|
|
InterfaceRec* =
|
|
RECORD
|
|
readByte*: ReadByteProc;
|
|
readChar*: ReadCharProc;
|
|
readBoolean*: ReadBooleanProc;
|
|
readShortInt*: ReadShortIntProc;
|
|
readInteger*: ReadIntegerProc;
|
|
readLongInt*: ReadLongIntProc;
|
|
readReal*: ReadRealProc;
|
|
readLongReal*: ReadLongRealProc;
|
|
readSet*: ReadSetProc;
|
|
readString*: ReadStringProc;
|
|
readConstString*: ReadConstStringProc;
|
|
|
|
writeByte*: WriteByteProc;
|
|
writeChar*: WriteCharProc;
|
|
writeBoolean*: WriteBooleanProc;
|
|
writeShortInt*: WriteShortIntProc;
|
|
writeInteger*: WriteIntegerProc;
|
|
writeLongInt*: WriteLongIntProc;
|
|
writeReal*: WriteRealProc;
|
|
writeLongReal*: WriteLongRealProc;
|
|
writeSet*: WriteSetProc;
|
|
writeString*: WriteStringProc;
|
|
writeConstString*: WriteConstStringProc;
|
|
END;
|
|
|
|
(* private data structures *)
|
|
TYPE
|
|
Discipline = POINTER TO DisciplineRec;
|
|
DisciplineRec =
|
|
RECORD
|
|
(Disciplines.DisciplineRec)
|
|
if: Interface;
|
|
END;
|
|
VAR
|
|
discID: Disciplines.Identifier;
|
|
|
|
PROCEDURE Swap (VAR a : ARRAY OF SYS.BYTE);
|
|
VAR
|
|
i,j : LONGINT;
|
|
tmp : SYS.BYTE;
|
|
BEGIN
|
|
i := 0; j := LEN (a) - 1;
|
|
WHILE i < j DO
|
|
tmp := a[i]; a[i] := a[j]; a[j] := tmp;
|
|
INC (i); DEC (j);
|
|
END;
|
|
END Swap;
|
|
|
|
PROCEDURE BitSwap (VAR a : ARRAY OF SYS.BYTE);
|
|
VAR
|
|
i,old, bit : LONGINT;
|
|
new : LONGINT;
|
|
|
|
BEGIN
|
|
i := 0;
|
|
WHILE i < LEN (a) DO
|
|
old := ORD (SYS.VAL (CHAR, a[i]));
|
|
new := 0; bit := 080H;
|
|
WHILE old # 0 DO
|
|
IF ODD (old) THEN
|
|
INC (new, bit);
|
|
END;
|
|
bit := ASH (bit, -1);;
|
|
old := ASH (old, -1);
|
|
END;
|
|
a[i] := SYS.VAL (SYS.BYTE, new);
|
|
INC (i);
|
|
END;
|
|
END BitSwap;
|
|
|
|
PROCEDURE ^ Forward(from, to: Forwarders.Object);
|
|
|
|
PROCEDURE AttachInterface*(s: Streams.Stream; if: Interface);
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF if # NIL THEN
|
|
NEW(disc); disc.id := discID; disc.if := if;
|
|
Disciplines.Add(s, disc);
|
|
ELSE
|
|
Disciplines.Remove(s, discID);
|
|
END;
|
|
Forwarders.Update(s, Forward);
|
|
END AttachInterface;
|
|
|
|
PROCEDURE GetInterface(s: Streams.Stream; VAR if: Interface);
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
if := disc.if;
|
|
ELSE
|
|
if := NIL;
|
|
END;
|
|
END GetInterface;
|
|
|
|
PROCEDURE CopyInterface*(from, to: Streams.Stream);
|
|
VAR
|
|
if: Interface;
|
|
BEGIN
|
|
GetInterface(from, if);
|
|
AttachInterface(to, if);
|
|
END CopyInterface;
|
|
|
|
PROCEDURE Forward(from, to: Forwarders.Object);
|
|
BEGIN
|
|
(* this check is necessary because of Forwarders.Update *)
|
|
IF ~(from IS Streams.Stream) OR ~(to IS Streams.Stream) THEN
|
|
RETURN
|
|
END;
|
|
|
|
WITH from: Streams.Stream DO WITH to: Streams.Stream DO
|
|
(* be careful here, from & to must be reversed *)
|
|
CopyInterface(to, from);
|
|
END; END;
|
|
END Forward;
|
|
|
|
PROCEDURE ReadByte*(s: Streams.Stream; VAR byte: Byte) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readByte(s, byte)
|
|
ELSE
|
|
RETURN Streams.ReadByte(s, byte)
|
|
END;
|
|
END ReadByte;
|
|
|
|
PROCEDURE ReadChar*(s: Streams.Stream; VAR char: CHAR) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readChar(s, char)
|
|
ELSE
|
|
RETURN Streams.ReadByte(s, char)
|
|
END;
|
|
END ReadChar;
|
|
|
|
PROCEDURE ReadBoolean*(s: Streams.Stream; VAR boolean: BOOLEAN) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readBoolean(s, boolean)
|
|
ELSE
|
|
RETURN Streams.Read(s, boolean)
|
|
END;
|
|
END ReadBoolean;
|
|
|
|
PROCEDURE ReadShortInt*(s: Streams.Stream; VAR shortint: SHORTINT) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readShortInt(s, shortint)
|
|
ELSE
|
|
RETURN Streams.ReadByte(s, shortint)
|
|
END;
|
|
END ReadShortInt;
|
|
|
|
PROCEDURE ReadInteger*(s: Streams.Stream; VAR integer: INTEGER) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
ret : BOOLEAN;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readInteger(s, integer)
|
|
ELSE
|
|
ret := Streams.Read(s, integer);
|
|
IF Types.byteorder = Types.littleEndian THEN
|
|
Swap (integer);
|
|
END;
|
|
RETURN ret;
|
|
END;
|
|
END ReadInteger;
|
|
|
|
PROCEDURE ReadLongInt*(s: Streams.Stream; VAR longint: LONGINT) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
ret : BOOLEAN;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readLongInt(s, longint)
|
|
ELSE
|
|
ret := Streams.Read(s, longint);
|
|
IF Types.byteorder = Types.littleEndian THEN
|
|
Swap (longint);
|
|
END;
|
|
RETURN ret;
|
|
END;
|
|
END ReadLongInt;
|
|
|
|
PROCEDURE ReadReal*(s: Streams.Stream; VAR real: REAL) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readReal(s, real)
|
|
ELSE
|
|
RETURN Streams.Read(s, real)
|
|
END;
|
|
END ReadReal;
|
|
|
|
PROCEDURE ReadLongReal*(s: Streams.Stream; VAR longreal: LONGREAL) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readLongReal(s, longreal)
|
|
ELSE
|
|
RETURN Streams.Read(s, longreal)
|
|
END;
|
|
END ReadLongReal;
|
|
|
|
PROCEDURE ReadSet*(s: Streams.Stream; VAR set: SET) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
ret : BOOLEAN;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readSet(s, set)
|
|
ELSE
|
|
ret := Streams.Read(s, set);
|
|
IF Types.byteorder = Types.littleEndian THEN
|
|
BitSwap (set);
|
|
END;
|
|
RETURN ret;
|
|
END;
|
|
END ReadSet;
|
|
|
|
PROCEDURE ReadString*(s: Streams.Stream; VAR string: ARRAY OF CHAR) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
ch: CHAR; index: LONGINT;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readString(s, string)
|
|
ELSE
|
|
index := 0;
|
|
WHILE Streams.ReadByte(s, ch) & (ch # 0X) DO
|
|
IF index + 1 < LEN(string) THEN
|
|
string[index] := ch; INC(index);
|
|
END;
|
|
END;
|
|
string[index] := 0X;
|
|
RETURN ~s.error
|
|
END;
|
|
END ReadString;
|
|
|
|
PROCEDURE ReadConstStringD*(s: Streams.Stream;
|
|
domain: ConstStrings.Domain;
|
|
VAR string: ConstStrings.String) : BOOLEAN;
|
|
CONST
|
|
bufsize = 512;
|
|
VAR
|
|
length: LONGINT;
|
|
buf: Streams.Stream;
|
|
ch: CHAR;
|
|
disc: Discipline;
|
|
stringbuf: ARRAY bufsize OF CHAR;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.readConstString(s, domain, string)
|
|
ELSE
|
|
IF ReadLongInt(s, length) THEN
|
|
IF length >= bufsize THEN
|
|
ConstStrings.Init(buf);
|
|
IF ~Streams.Copy(s, buf, length) THEN
|
|
RETURN FALSE
|
|
END;
|
|
ConstStrings.CloseD(buf, domain, string);
|
|
RETURN length = s.count;
|
|
ELSE
|
|
IF ~Streams.ReadPart(s, stringbuf, 0, length) THEN
|
|
RETURN FALSE
|
|
END;
|
|
stringbuf[length] := 0X;
|
|
ConstStrings.CreateD(string, domain, stringbuf);
|
|
RETURN TRUE
|
|
END;
|
|
ELSE
|
|
RETURN FALSE
|
|
END;
|
|
END;
|
|
END ReadConstStringD;
|
|
|
|
PROCEDURE ReadConstString*(s: Streams.Stream;
|
|
VAR string: ConstStrings.String) : BOOLEAN;
|
|
BEGIN
|
|
RETURN ReadConstStringD(s, ConstStrings.std, string)
|
|
END ReadConstString;
|
|
|
|
PROCEDURE WriteByte*(s: Streams.Stream; byte: Byte) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeByte(s, byte)
|
|
ELSE
|
|
RETURN Streams.WriteByte(s, byte)
|
|
END;
|
|
END WriteByte;
|
|
|
|
PROCEDURE WriteChar*(s: Streams.Stream; char: CHAR) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeChar(s, char)
|
|
ELSE
|
|
RETURN Streams.WriteByte(s, char)
|
|
END;
|
|
END WriteChar;
|
|
|
|
PROCEDURE WriteBoolean*(s: Streams.Stream; boolean: BOOLEAN) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeBoolean(s, boolean)
|
|
ELSE
|
|
RETURN Streams.Write(s, boolean)
|
|
END;
|
|
END WriteBoolean;
|
|
|
|
PROCEDURE WriteShortInt*(s: Streams.Stream; shortint: SHORTINT) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeShortInt(s, shortint)
|
|
ELSE
|
|
RETURN Streams.WriteByte(s, shortint)
|
|
END;
|
|
END WriteShortInt;
|
|
|
|
PROCEDURE WriteInteger*(s: Streams.Stream; integer: INTEGER) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeInteger(s, integer)
|
|
ELSE
|
|
IF Types.byteorder = Types.littleEndian THEN
|
|
Swap (integer);
|
|
END;
|
|
RETURN Streams.Write(s, integer);
|
|
END;
|
|
END WriteInteger;
|
|
|
|
PROCEDURE WriteLongInt*(s: Streams.Stream; longint: LONGINT) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeLongInt(s, longint)
|
|
ELSE
|
|
IF Types.byteorder = Types.littleEndian THEN
|
|
Swap (longint);
|
|
END;
|
|
RETURN Streams.Write(s, longint);
|
|
END;
|
|
END WriteLongInt;
|
|
|
|
PROCEDURE WriteReal*(s: Streams.Stream; real: REAL) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeReal(s, real)
|
|
ELSE
|
|
RETURN Streams.Write(s, real)
|
|
END;
|
|
END WriteReal;
|
|
|
|
PROCEDURE WriteLongReal*(s: Streams.Stream; longreal: LONGREAL) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeLongReal(s, longreal)
|
|
ELSE
|
|
RETURN Streams.Write(s, longreal)
|
|
END;
|
|
END WriteLongReal;
|
|
|
|
PROCEDURE WriteSet*(s: Streams.Stream; set: SET) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeSet(s, set)
|
|
ELSE
|
|
IF Types.byteorder = Types.littleEndian THEN
|
|
BitSwap (set);
|
|
END;
|
|
RETURN Streams.Write(s, set)
|
|
END;
|
|
END WriteSet;
|
|
|
|
PROCEDURE WriteString*(s: Streams.Stream; string: ARRAY OF CHAR) : BOOLEAN;
|
|
VAR
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeString(s, string)
|
|
ELSE
|
|
RETURN Streams.WritePart(s, string, 0, Strings.Len(string)) &
|
|
Streams.WriteByte(s, 0X)
|
|
END;
|
|
END WriteString;
|
|
|
|
PROCEDURE WriteConstString*(s: Streams.Stream;
|
|
string: ConstStrings.String) : BOOLEAN;
|
|
VAR
|
|
ch: CHAR;
|
|
buf: Streams.Stream;
|
|
disc: Discipline;
|
|
BEGIN
|
|
IF Disciplines.Seek(s, discID, SYS.VAL(Disciplines.Discipline, disc)) THEN
|
|
RETURN disc.if.writeConstString(s, string)
|
|
ELSE
|
|
IF WriteLongInt(s, string.len) THEN
|
|
ConstStrings.Open(buf, string);
|
|
RETURN Streams.Copy(buf, s, string.len)
|
|
ELSE
|
|
RETURN FALSE
|
|
END;
|
|
END;
|
|
END WriteConstString;
|
|
|
|
BEGIN
|
|
discID := Disciplines.Unique();
|
|
Forwarders.Register("Streams.Stream", Forward);
|
|
END ulmNetIO.
|