<> <> <> <<>> <> <<>> DIRECTORY Ascii USING [DEL, NUL], Basics USING [ByteBlt, charsPerWord, RawBytes, UnsafeBlock], IO USING [STREAM], Rope USING [FromChar, Length, NewText, ROPE, Text, UnsafeMoveChars], YggDID USING [], YggFile USING [FileHandle], YggFileStream USING [OpenFileInDirectory, OpenStreamInDirectory], YggInline USING [BytesForWords, WordsForBytes]; YggDIDImpl: CEDAR PROGRAM IMPORTS Rope, YggFileStream, YggInline EXPORTS YggDID, YggFile SHARES Rope -- for messing with Rope.TextRep ~ BEGIN ROPE: TYPE ~ Rope.ROPE; DID: PUBLIC TYPE ~ REF DIDRep; DIDRep: PUBLIC TYPE ~ ROPE; <> FirstDID: PUBLIC DID ; LastDID: PUBLIC DID ; AllNulls: PACKED ARRAY [0..Basics.charsPerWord) OF CHAR _ ALL[0C]; <> StreamsForDID: PUBLIC PROC [did: DID] RETURNS [contents, attributes, links: IO.STREAM _ NIL] ~ { <> contents _ YggFileStream.OpenStreamInDirectory[did, "$contents"]; attributes _ YggFileStream.OpenStreamInDirectory[did, "$attributes"]; links _ YggFileStream.OpenStreamInDirectory[did, "$links"]; }; <<>> FilesForDID: PUBLIC PROC [did: DID] RETURNS [contents, attributes, links: YggFile.FileHandle _ NIL] ~ { <> contents _ YggFileStream.OpenFileInDirectory[did, "$contents"]; attributes _ YggFileStream.OpenFileInDirectory[did, "$attributes"]; links _ YggFileStream.OpenFileInDirectory[did, "$links"]; }; <<>> SizeForDID: PUBLIC PROC [did: DID] RETURNS [bytes: INT] = { <> ddd: DIDRep; ddd _ did^; bytes _ YggInline.BytesForWords[YggInline.WordsForBytes[Rope.Length[did^]]]; }; <<>> StabilizeDID: PUBLIC PROC [did: DID, buffer: LONG POINTER] = { <> size: INT; nBytes: INT; nullsToMove: INT; size _ Rope.Length[did^]; TRUSTED {nBytes _ Rope.UnsafeMoveChars[block: [buffer, 0, size], rope: did^, start: 0];}; IF nBytes # size THEN ERROR; nullsToMove _ YggInline.BytesForWords[YggInline.WordsForBytes[size+1]] - size; IF nullsToMove <= 0 THEN ERROR; TRUSTED {nBytes _ Basics.ByteBlt[ from: [blockPointer: @AllNulls, startIndex: 0, stopIndexPlusOne: nullsToMove], to: [blockPointer: buffer, startIndex: size, stopIndexPlusOne: size+nullsToMove]]; }; IF nBytes # nullsToMove THEN ERROR; }; <<>> VolatilizeDID: PUBLIC PROC [buffer: LONG POINTER] RETURNS [did: DID] = { <> charBuffer: LONG POINTER TO ARRAY [0..0] OF CHAR; scratch: Rope.Text; scratchRope: ROPE; lenKey: INT; charBuffer _ LOOPHOLE[buffer]; FOR lenKey IN [ 0 .. NAT15.LAST ) DO TRUSTED {IF charBuffer[lenKey] = Ascii.NUL THEN EXIT;}; ENDLOOP; scratch _ Rope.NewText[lenKey]; FOR charNo: INT IN [ 0 .. lenKey ) DO TRUSTED {scratch[charNo] _ charBuffer[charNo];}; ENDLOOP; scratch.length _ lenKey; did _ NEW[DIDRep]; scratchRope _ scratch; did^ _ scratchRope; }; <<>> <<>> <> FirstDID _ NEW[DIDRep]; FirstDID^ _ ""; LastDID _ NEW[DIDRep]; LastDID^ _ Rope.FromChar[Ascii.DEL]; END.