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;
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: ROPE ← NARROW [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: ROPE ← NARROW [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 ROPE ← NIL;
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];
};