<<>> <> <> <> <> <> DIRECTORY CrRPC, IO, Rope, SerializedFiling; SerializedFilingImpl: CEDAR PROGRAM IMPORTS CrRPC, IO, Rope EXPORTS SerializedFiling ~ BEGIN OPEN SerializedFiling; STREAM: TYPE ~ IO.STREAM; Error: PUBLIC ERROR [reason: ATOM, exp: ROPE] = CODE; <> GetSerializedFile: PUBLIC PROC [s: STREAM] RETURNS [sfout: SerializedFile] ~ { <> sfout.version ¬ CrRPC.GetCard32[s]; sfout.file ¬ GetSerializedTree[s]; }; <<>> PutSerializedFile: PUBLIC PROC [s: STREAM, sfin: SerializedFile] ~ { <> CrRPC.PutCard32[s, sfin.version]; PutSerializedTree[s, sfin.file]; }; GetRopeContents: PUBLIC PROC [sf: SerializedFile] RETURNS [contents: ROPE] ~ { <> contents ¬ NIL; FOR uL: StreamOfUnspecified ¬ sf.file.content.data, uL.rest WHILE uL#NIL DO rope: ROPE ¬ RopeFromSegment[segment: uL.first, lastByteIsSignificant: uL.rest # NIL OR sf.file.content.lastByteIsSignificant]; contents ¬ Rope.Concat[base: contents, rest: rope]; ENDLOOP; RETURN[contents]; }; SetRopeContents: PUBLIC PROC [sf: SerializedFile, contents: ROPE] RETURNS [new: SerializedFile] ~ { <> segment: Segment; [segment, sf.file.content.lastByteIsSignificant] ¬ SegmentFromRope[contents]; sf.file.content.data ¬ LIST[segment]; RETURN[sf]; }; GetAttributeAsRope: PUBLIC PROC [sf: SerializedFile, type: AttributeType] RETURNS [value: ROPE ¬ NIL] ~ { <> FOR i: CARDINAL IN [0..sf.file.attributes.length) DO attr: Attribute ¬ sf.file.attributes.body[i]; IF attr.type = type THEN { value ¬ RopeFromSegment[attr.value]; EXIT; }; ENDLOOP; RETURN[value]; }; <<>> SetAttributeFromRope: PUBLIC PROC [sf: SerializedFile, type: AttributeType, value: ROPE] RETURNS [new: SerializedFile] ~ { <> lastByteIsSignificant: BOOL ¬ FALSE; FOR i: CARDINAL IN [0..sf.file.attributes.length) DO IF sf.file.attributes.body[i].type = type THEN { [sf.file.attributes.body[i].value, lastByteIsSignificant] ¬ SegmentFromRope[value]; EXIT; }; ENDLOOP; IF lastByteIsSignificant THEN ERROR Error[$SetAttributeFromRope, "Attributes must be an even number of bytes"]; RETURN[sf]; }; <<>> GetRopeAttribute: PUBLIC PROC [sf: SerializedFile, type: AttributeType] RETURNS [value: ROPE] = { <> FOR i: CARDINAL IN [0..sf.file.attributes.length) DO attr: Attribute ¬ sf.file.attributes.body[i]; IF attr.type = type THEN { segment: Segment ~ sf.file.attributes.body[i].value; s: STREAM ¬ IO.ROS[]; FOR i: CARDINAL IN [0..segment.length) DO CrRPC.PutCard16[s, segment.body[i]]; ENDLOOP; value ¬ CrRPC.GetRope[IO.RIS[IO.RopeFromROS[s]]]; EXIT; }; ENDLOOP; RETURN[value]; }; SetRopeAttribute: PUBLIC PROC [sf: SerializedFile, type: AttributeType, value: ROPE] RETURNS [new: SerializedFile] = { <> <> FOR i: CARDINAL IN [0..sf.file.attributes.length) DO IF sf.file.attributes.body[i].type = type THEN { s: STREAM ¬ IO.ROS[]; CrRPC.PutRope[s, value]; sf.file.attributes.body[i].value ¬ SegmentFromRope[IO.RopeFromROS[s]].segment; EXIT; }; ENDLOOP; RETURN[sf]; }; GetVersionedRopeAttribute: PUBLIC PROC [sf: SerializedFile, type: AttributeType] RETURNS [version: CARD16 ¬ 0, value: ROPE ¬ NIL] = { <> FOR i: CARDINAL IN [0..sf.file.attributes.length) DO IF sf.file.attributes.body[i].type = type THEN { segment: Segment ¬ sf.file.attributes.body[i].value; s: STREAM ¬ IO.ROS[]; FOR i: CARDINAL IN [1..segment.length) DO CrRPC.PutCard16[s, segment.body[i]]; ENDLOOP; value ¬ CrRPC.GetRope[IO.RIS[IO.RopeFromROS[s]]]; version ¬ segment.body[0]; EXIT; }; ENDLOOP; RETURN[version, value]; }; SetVersionedRopeAttribute: PUBLIC PROC [sf: SerializedFile, type: AttributeType, version: CARD16, value: ROPE] RETURNS [new: SerializedFile] = { <> <> FOR i: CARDINAL IN [0..sf.file.attributes.length) DO IF sf.file.attributes.body[i].type = type THEN { s: STREAM ¬ IO.ROS[]; CrRPC.PutCard16[s, version]; CrRPC.PutRope[s, value]; sf.file.attributes.body[i].value ¬ SegmentFromRope[IO.RopeFromROS[s]].segment; EXIT; }; ENDLOOP; RETURN[sf]; }; RopeFromSegment: PUBLIC PROC [segment: Segment, lastByteIsSignificant: BOOLEAN ¬ TRUE] RETURNS [rope: ROPE] ~ { <> <> s: STREAM ¬ IO.ROS[]; FOR i: CARDINAL IN [0..segment.length) DO CrRPC.PutCard16[s, segment.body[i]]; ENDLOOP; rope ¬ IO.RopeFromROS[s]; IF NOT lastByteIsSignificant THEN -- remove last char rope ¬ Rope.Substr[base: rope, start: 0, len: Rope.Length[base: rope]-1]; }; <<>> SegmentFromRope: PUBLIC PROC [rope: ROPE] RETURNS [segment: Segment, lastByteIsSignificant: BOOLEAN] ~ { <> <> length8: CARDINAL ¬ Rope.Length[base: rope]; length16: CARDINAL ¬ (length8+1)/2; s: STREAM; segment ¬ NEW[SegmentObject[length16]]; lastByteIsSignificant ¬ length8 MOD 2 = 0; s ¬ IO.RIS[rope: IF lastByteIsSignificant THEN rope ELSE Rope.Concat[base: rope, rest: "\000"]]; FOR i: CARDINAL IN [0..length16) DO segment.body[i] ¬ CrRPC.GetCard16[s]; ENDLOOP; }; <<>> <> GetSerializedTree: PROC [s: CrRPC.STREAM] RETURNS [res: SerializedTree] ~ { res.attributes ¬ GetAttributeSequence[s]; res.content.data ¬ GetStreamOfUnspecified[s]; res.content.lastByteIsSignificant ¬ CrRPC.GetBool[s]; res.children ¬ GetSerializedTreeSequence[s]; }; PutSerializedTree: PROC [s: CrRPC.STREAM, val: SerializedTree] ~ { PutAttributeSequence[s, val.attributes]; PutStreamOfUnspecified[s, val.content.data]; CrRPC.PutBool[s, val.content.lastByteIsSignificant]; PutSerializedTreeSequence[s, val.children]; }; <<>> <> <<>> nextSegment: CARD16 ¬ 0; lastSegment: CARD16 ¬ 1; GetStreamOfUnspecified: PROC [s: CrRPC.STREAM] RETURNS [res: StreamOfUnspecified] ~ { tail: StreamOfUnspecified ¬ NIL; res ¬ NIL; DO type: CARD16 ¬ CrRPC.GetCard16[s]; seg: Segment ¬ GetSegment[s]; IF tail = NIL THEN {tail ¬ res ¬ LIST[seg];} ELSE {tail.rest ¬ LIST[seg]; tail ¬ tail.rest;}; IF type = lastSegment THEN EXIT; ENDLOOP; }; PutStreamOfUnspecified: PROC [s: CrRPC.STREAM, val: StreamOfUnspecified] ~ { IF val = NIL THEN { CrRPC.PutCard16[s, lastSegment]; PutSegment[s, NIL]; RETURN; }; FOR uL: StreamOfUnspecified ¬ val, uL.rest WHILE uL#NIL DO CrRPC.PutCard16[s, IF uL.rest=NIL THEN lastSegment ELSE nextSegment]; PutSegment[s, uL.first]; ENDLOOP; }; GetAttributeSequence: PROC [s: CrRPC.STREAM] RETURNS [res: AttributeSequence] ~ { length16: CARDINAL ~ CrRPC.GetCard16[s]; res ¬ NEW[AttributeSequenceObject[length16]]; FOR i15: CARDINAL IN [0..length16) DO res.body[i15].type ¬ CrRPC.GetCard32[s]; res.body[i15].value ¬ GetAttributeValue[s]; ENDLOOP; }; PutAttributeSequence: PROC [s: CrRPC.STREAM, val: AttributeSequence] ~ { IF val = NIL THEN { CrRPC.PutCard16[s, 0]; RETURN; }; CrRPC.PutCard16[s, val.length]; FOR i20: CARDINAL IN [0..val.length) DO CrRPC.PutCard32[s, val.body[i20].type]; PutAttributeValue[s, val.body[i20].value]; ENDLOOP; }; GetAttributeValue: PROC [s: CrRPC.STREAM] RETURNS [res: AttributeValue] ~ { length19: CARDINAL ~ CrRPC.GetCard16[s]; res ¬ NEW[AttributeValueObject[length19]]; FOR i18: CARDINAL IN [0..length19) DO res.body[i18] ¬ CrRPC.GetCard16[s]; ENDLOOP; }; PutAttributeValue: PROC [s: CrRPC.STREAM, val: AttributeValue] ~ { IF val = NIL THEN { CrRPC.PutCard16[s, 0]; RETURN; }; CrRPC.PutCard16[s, val.length]; FOR i25: CARDINAL IN [0..val.length) DO CrRPC.PutCard16[s, val.body[i25]]; ENDLOOP; }; GetSegment: PROC [s: CrRPC.STREAM] RETURNS [res: Segment] ~ { length24: CARDINAL ~ CrRPC.GetCard16[s]; res ¬ NEW[SegmentObject[length24]]; FOR i23: CARDINAL IN [0..length24) DO res.body[i23] ¬ CrRPC.GetCard16[s]; ENDLOOP; }; PutSegment: PROC [s: CrRPC.STREAM, val: Segment] ~ { IF val = NIL THEN { CrRPC.PutCard16[s, 0]; RETURN; }; CrRPC.PutCard16[s, val.length]; FOR i22: CARDINAL IN [0..val.length) DO CrRPC.PutCard16[s, val.body[i22]]; ENDLOOP; }; GetSerializedTreeSequence: PROC [s: CrRPC.STREAM] RETURNS [res: SerializedTreeSequence] ~ { length24: CARDINAL ~ CrRPC.GetCard16[s]; res ¬ NEW[SerializedTreeSequenceObject[length24]]; FOR i23: CARDINAL IN [0..length24) DO res.body[i23] ¬ GetSerializedTree[s]; ENDLOOP; }; PutSerializedTreeSequence: PROC [s: CrRPC.STREAM, val: SerializedTreeSequence] ~ { IF val = NIL THEN { CrRPC.PutCard16[s, 0]; RETURN; }; CrRPC.PutCard16[s, val.length]; FOR i22: CARDINAL IN [0..val.length) DO PutSerializedTree[s, val.body[i22]]; ENDLOOP; }; END.