BrineIOImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet May 4, 1988 11:15:43 pm PDT
Bertrand Serlet May 7, 1988 4:33:58 pm PDT
DIRECTORY
Ascii, Atom, BasicTime, Convert, IO, RefTab, RefTabExtras, Rope, BrineIO;
BrineIOImpl: CEDAR PROGRAM
IMPORTS Atom, BasicTime, Convert, IO, RefTab, RefTabExtras, Rope
EXPORTS BrineIO
= BEGIN OPEN BrineIO;
Prerequisites
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
PutSpace: PROC [stream: STREAM] = INLINE {IO.PutChar[stream, Ascii.SP]};
Basic Read/Write Functions
ReadInt: PUBLIC PROC [stream: STREAM] RETURNS [int: INT] = {
int ← IO.GetInt[stream];
};
WriteInt: PUBLIC PROC [stream: STREAM, int: INT] = {
We use Put1 instead of PutF to be faster.
IO.Put1[stream, IO.int[int]]; PutSpace[stream];
};
ReadBool: PUBLIC PROC [stream: STREAM] RETURNS [bool: BOOL] = {
bool ← ReadInt[stream]#0;
};
WriteBool: PUBLIC PROC [stream: STREAM, bool: BOOL] = {
WriteInt[stream, IF bool THEN 1 ELSE 0];
};
ReadReal: PUBLIC PROC [stream: STREAM] RETURNS [real: REAL] = {
real ← IO.GetReal[stream];
};
WriteReal: PUBLIC PROC [stream: STREAM, real: REAL] = {
IO.Put1[stream, IO.real[real]]; PutSpace[stream];
};
ReadGMT: PUBLIC PROC [stream: STREAM] RETURNS [gmt: BasicTime.GMT] = {
gmt ← BasicTime.FromNSTime[LOOPHOLE [ReadInt[stream], CARD]];
};
WriteGMT: PUBLIC PROC [stream: STREAM, gmt: BasicTime.GMT] = {
WriteInt[stream, LOOPHOLE [BasicTime.ToNSTime[gmt], INT]];
};
ReadAtom: PUBLIC PROC [stream: STREAM] RETURNS [atom: ATOM] = {
atomIDTable: RefTab.Ref ← GetRefTab[stream, $BrineIOAtomTable, RefTabExtras.EqualRope, RefTabExtras.HashRope];
atomID: ROPE ← ReadID[stream];
IF Rope.Fetch[atomID]#'A THEN ERROR;
atom ← NARROW [RefTab.Fetch[atomIDTable, atomID].val];
IF atom=NIL THEN {
atom ← IO.GetAtom[stream];
IF NOT RefTab.Insert[atomIDTable, atomID, atom] THEN ERROR;
};
};
WriteAtom: PUBLIC PROC [stream: STREAM, atom: ATOM] = {
atomIDTable: RefTab.Ref ← GetRefTab[stream, $BrineIOAtomTable];
atomID: ROPENARROW [RefTab.Fetch[atomIDTable, atom].val];
IF atomID=NIL THEN {
atomID ← MakeID["A", RefTab.GetSize[atomIDTable]];
IF NOT RefTab.Insert[atomIDTable, atom, atomID] THEN ERROR;
WriteID[stream, atomID];
IO.Put1[stream, IO.atom[atom]]; PutSpace[stream];
}
ELSE WriteID[stream, atomID];
};
ReadID: PUBLIC PROC [stream: STREAM] RETURNS [id: ROPE] = {
id ← IO.GetID[stream];
};
WriteID: PUBLIC PROC [stream: STREAM, id: ROPE] = {
IO.PutRope[stream, id]; PutSpace[stream];
};
ReadRope: PUBLIC PROC [stream: STREAM] RETURNS [rope: ROPE] = {
ropeIDTable: RefTab.Ref ← GetRefTab[stream, $BrineIORopeTable, RefTabExtras.EqualRope, RefTabExtras.HashRope];
ropeID: ROPE ← ReadID[stream];
IF Rope.Fetch[ropeID]#'R THEN ERROR;
rope ← NARROW [RefTab.Fetch[ropeIDTable, ropeID].val];
IF rope=NIL THEN {
rope ← IO.GetRopeLiteral[stream];
IF NOT RefTab.Insert[ropeIDTable, ropeID, rope] THEN ERROR;
};
};
doubleQuote: CHAR = '";
backSlash: CHAR = '\\;
doubleQuoteRope: ROPE = Rope.FromChar[doubleQuote];
WriteRope: PUBLIC PROC [stream: STREAM, rope: ROPE] = {
ropeIDTable: RefTab.Ref ← GetRefTab[stream, $BrineIORopeTable];
ropeID: ROPENARROW [RefTab.Fetch[ropeIDTable, rope].val];
IF ropeID=NIL THEN {
ropeID ← MakeID["R", RefTab.GetSize[ropeIDTable]];
IF NOT RefTab.Insert[ropeIDTable, rope, ropeID] THEN ERROR;
WriteID[stream, ropeID];
IO.PutChar[stream, doubleQuote];
we cannot use IO.PutF that truncates long ropes, and we have to beware of "!
WHILE NOT Rope.IsEmpty[rope] DO
index: INT ← Rope.Find[rope, doubleQuoteRope];
IF index<0
THEN {IO.PutRope[stream, rope]; rope ← NIL}
ELSE {
IO.PutRope[stream, rope, 0, index];
IO.PutChar[stream, backSlash];
IO.PutChar[stream, doubleQuote];
rope ← Rope.Substr[rope, index+1];
};
ENDLOOP;
IO.PutChar[stream, doubleQuote];
PutSpace[stream];
}
ELSE WriteID[stream, ropeID];
};
Composite Read/Write Functions
ReadAtomRef: PUBLIC PROC [stream: STREAM] RETURNS [REF] = {RETURN [ReadAtom[stream]]};
WriteAtomRef: PUBLIC PROC [stream: STREAM, ref: REF] = {WriteAtom[stream, NARROW [ref]]};
ReadIDRef: PUBLIC PROC [stream: STREAM] RETURNS [REF] = {RETURN [ReadID[stream]]};
WriteIDRef: PUBLIC PROC [stream: STREAM, ref: REF] = {WriteID[stream, NARROW [ref]]};
ReadRopeRef: PUBLIC PROC [stream: STREAM] RETURNS [REF] = {RETURN [ReadRope[stream]]};
WriteRopeRef: PUBLIC PROC [stream: IO.STREAM, ref: REF] = {WriteRope[stream, NARROW [ref]]};
ReadRopes: PUBLIC PROC [stream: STREAM] RETURNS [ropes: LIST OF ROPE] = {
count: INT ← ReadInt[stream];
lor: LIST OF ROPENIL;
FOR c: INT IN [0 .. count) DO
lor ← CONS [ReadRope[stream], lor];
ENDLOOP;
FOR rl: LIST OF ROPE ← lor, rl.rest UNTIL rl=NIL DO
ropes ← CONS [rl.first, ropes];
ENDLOOP;
};
WriteRopes: PUBLIC PROC [stream: STREAM, ropes: LIST OF ROPE] = {
count: INT ← 0;
FOR rl: LIST OF ROPE ← ropes, rl.rest UNTIL rl=NIL DO
count ← count + 1;
ENDLOOP;
WriteInt[stream, count];
FOR rl: LIST OF ROPE ← ropes, rl.rest UNTIL rl=NIL DO
WriteRope[stream, rl.first];
ENDLOOP;
};
ReadRefTab: PUBLIC PROC [stream: STREAM, readKey, readVal: ReadRefProc, equal: RefTab.EqualProc ← NIL, hash: RefTab.HashProc ← NIL] RETURNS [table: RefTab.Ref] = {
size: INT ← ReadInt[stream];
table ← RefTab.Create[mod: (size/2)*2+1, equal: equal, hash: hash];
THROUGH [0 .. size) DO
key: REF ← readKey[stream];
val: REF ← readVal[stream];
IF NOT RefTab.Insert[table, key, val] THEN ERROR;
ENDLOOP;
};
WriteRefTab: PUBLIC PROC [stream: STREAM, table: RefTab.Ref, writeKey, writeVal: WriteRefProc] = {
HashPair: RefTab.EachPairAction = {writeKey[stream, key]; writeVal[stream, val]};
WriteInt[stream, RefTab.GetSize[table]];
IF RefTab.Pairs[table, HashPair] THEN ERROR;
};
Utilities
MakeID: PUBLIC PROC [prefix: ROPE, int: INT] RETURNS [ROPE] = {
RETURN [Rope.Cat[prefix, Convert.RopeFromInt[from: int, base: 16, showRadix: FALSE]]];
};
GetRefTab: PUBLIC PROC [stream: STREAM, key: ATOM, equal: RefTab.EqualProc ← NIL, hash: RefTab.HashProc ← NIL] RETURNS [table: RefTab.Ref] = {
table ← NARROW [Atom.GetPropFromList[stream.propList, key]];
IF table#NIL THEN RETURN;
table ← RefTab.Create[equal: equal, hash: hash];
stream.propList ← Atom.PutPropOnList[stream.propList, key, table];
};
END.