PROC [transID: YggEnvironment.TransID, did: YggDID.
DID, document: YggRep.VDoc, contents, attributes, links: YggFile.FileHandle] ~ {
writeAttribute:
PROC [attribute: YggRep.Attribute] = {
Given an attribute, write it out to the stream. See YggRep.mesa for a description of what the format is.
writeBits:
PROC [tpe: YggRep.TypedPrimitiveElement] = {
Write the contents of a TypedPrimitiveElement. The type has already been writen.
SELECT tpe.docType
FROM
YggRep.unknown => ERROR;
YggRep.int => {
ri: REF INT32;
ri ← NARROW[tpe.bits];
writeInt[ri^];
};
YggRep.shortRope => {
rRope: ROPE;
rRope ← NARROW[tpe.bits];
writeString[rRope, 0];
};
YggRep.rope => {
len: INT;
rRope: ROPE;
rRope ← NARROW[tpe.bits];
len ← Rope.Length[rRope];
writeInt[len];
writeString[rRope, 0];
};
YggRep.float => {
rReal: REF REAL32;
rReal ← NARROW[tpe.bits];
TRUSTED {
ptReal: POINTER TO REAL32;
ptReal ← LOOPHOLE[rReal];
IO.UnsafePutBlock[attributesStream, [LOOPHOLE[ptReal], 0, Basics.charsPerWord]];
};
};
YggRep.date => {
rAccurateGMT: YggRep.AccurateGMT;
rAccurateGMT ← NARROW[tpe.bits];
TRUSTED {
ptAGMT: POINTER TO YggRep.AccurateGMTRep;
ptAGMT ← LOOPHOLE[rAccurateGMT];
IO.UnsafePutBlock[attributesStream, [LOOPHOLE[ptAGMT], 0, YggRep.AccurateGMTRepByteSize]];
};
};
ENDCASE => {
nullsToWrite: INT;
rBits: REF YggRep.BitsRep;
rBits ← NARROW[tpe.bits];
writeInt[rBits.length];
TRUSTED {
ptBits: POINTER TO YggRep.BitsRep;
ptBits ← LOOPHOLE[rBits];
IO.UnsafePutBlock[attributesStream, [LOOPHOLE[ptBits, POINTER TO Basics.RawBytes] + SIZE[YggRep.BitsRep[0]], 0, rBits.length]];
};
nullsToWrite ← Basics.charsPerWord - (rBits.length) MOD Basics.charsPerWord;
IF nullsToWrite > 0 THEN TRUSTED {IO.UnsafePutBlock[attributesStream, [LOOPHOLE[@AllNulls], 0 , nullsToWrite]];};
};
};
writeString:
PROC [string:
ROPE, extraChars:
INT] = {
len: INT;
nullsToWrite: INT;
len ← Rope.Length[string];
IF len > 0 THEN IO.PutRope[attributesStream, string];
nullsToWrite ← Basics.charsPerWord - (len+extraChars) MOD Basics.charsPerWord;
TRUSTED {IO.UnsafePutBlock[attributesStream, [LOOPHOLE[@AllNulls], 0 , nullsToWrite]];};
};
writeInt:
PROC [int:
INT] = {
TRUSTED {IO.UnsafePutBlock[attributesStream, [LOOPHOLE[@int], 0, Basics.charsPerWord]];};
};
nullFieldNames: BOOL ← TRUE;
singletonFieldValues: BOOL ← TRUE;
numberOfAttributeValues: INT ← 0;
primitiveType: YggRep.DocType ← YggRep.unknown;
preample: YggRep.AttributePreamble;
FOR rv:
LIST
OF YggRep.AttributeValue ← attribute.value, rv.rest
UNTIL rv =
NIL
DO
numberOfAttributeValues ← numberOfAttributeValues + 1;
IF rv.first.fieldName # NIL THEN nullFieldNames ← FALSE;
IF rv.first.valueSet.rest # NIL THEN singletonFieldValues ← FALSE;
FOR avl:
LIST
OF YggRep.TypedPrimitiveElement ← rv.first.valueSet, avl.rest
UNTIL avl =
NIL
DO
tpe: YggRep.TypedPrimitiveElement = avl.first;
IF tpe.docType < YggRep.date AND (primitiveType = YggRep.unknown OR primitiveType = tpe.docType) THEN primitiveType ← tpe.docType ELSE primitiveType ← 10000;
ENDLOOP;
ENDLOOP;
preample[0].ordered ← attribute.ordered;
preample[0].noFieldNames ← ~nullFieldNames;
preample[0].singletonAttribute ← (numberOfAttributeValues = 1);
preample[0].singletonField ← singletonFieldValues;
preample[0].typeCode ←
SELECT primitiveType
FROM
YggRep.int => integer,
YggRep.rope => ropeLarge,
YggRep.shortRope => ropeShort,
YggRep.float => float,
YggRep.date => date,
YggRep.uninterpretedBytes => uninterpretedBytes,
ENDCASE => separate;
IF numberOfAttributeValues <= 0 THEN RETURN;
writeInt[document.contents.docType];
TRUSTED {IO.PutChar[attributesStream, LOOPHOLE[@preample]];}; -- @preample points to preample[0]
writeString[attribute.attributeName, 1]; -- write attribute name
IF numberOfAttributeValues # 1 THEN writeInt[numberOfAttributeValues]; -- write number of attribute values;
FOR rv:
LIST
OF YggRep.AttributeValue ← attribute.value, rv.rest
UNTIL rv =
NIL
DO
IF ~nullFieldNames THEN writeString[rv.first.fieldName, 0]; -- write field name
FOR avl:
LIST
OF YggRep.TypedPrimitiveElement ← rv.first.valueSet, avl.rest
UNTIL avl =
NIL
DO
tpe: YggRep.TypedPrimitiveElement = avl.first;
IF preample[0].typeCode = separate THEN writeInt[tpe.docType];
writeBits[tpe];
ENDLOOP;
IF ~preample[0].singletonField THEN writeInt[YggRep.unknown];
ENDLOOP;
};