YggDIDImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bob Hagmann May 9, 1988 4:29:30 pm PDT
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];
~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
DID: PUBLIC TYPE ~ REF DIDRep;
DIDRep:
PUBLIC TYPE ~
ROPE;
For Phase 0, the DIDRep is just a string that names a directory (without the trailing /).
FirstDID: PUBLIC DID ;
LastDID: PUBLIC DID ;
AllNulls: PACKED ARRAY [0..Basics.charsPerWord) OF CHAR ← ALL[0C];
Exported procedures
StreamsForDID:
PUBLIC
PROC [did:
DID]
RETURNS [contents, attributes, links:
IO.
STREAM ←
NIL] ~ {
Get streams for the DID. Any or all of these objects may be NIL. For objects with few links, the links are stored in the attributes. For objects with small contents, the contents are stored in the attributes. If there are no attributes, there is no file for them.
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] ~ {
Get the file objects for the DID. Any or all of these objects may be NIL. For objects with few links, the links are stored in the attributes. For objects with small contents, the contents are stored in the attributes. If there are no attributes, there is no file for them.
contents ← YggFileStream.OpenFileInDirectory[did, "$contents"];
attributes ← YggFileStream.OpenFileInDirectory[did, "$attributes"];
links ← YggFileStream.OpenFileInDirectory[did, "$links"];
};
SizeForDID:
PUBLIC
PROC [did:
DID]
RETURNS [bytes:
INT] = {
Return the size of the did. The size in in bytes rounded up to the next word.
ddd: DIDRep;
ddd ← did^;
bytes ← YggInline.BytesForWords[YggInline.WordsForBytes[Rope.Length[did^]]];
};
StabilizeDID:
PUBLIC
PROC [did:
DID, buffer:
LONG
POINTER] = {
Take a DID and write it to a buffer.
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] = {
Take a buffer and construct a 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;
};