XNSFilingAttributeImpl.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Bill Jackson (bj), May 25, 1990 6:51 pm PDT
DIRECTORY
Basics USING [LongNumber, ShortNumber],
BasicTime USING [FromNSTime, GMT, nullGMT, OutOfRange, ToNSTime],
CHNameP2V0 USING [],
FilingAttributesP10V5 USING [AccessEntrySequence, AccessList, Attribute, AttributeSequence, AttributeSequenceObject, AttributeValue, AttributeValueObject, FileID, Interpretation, InterpretedAttributeType, nullFileID, Ordering, Position, PositionObject, User],
FilingP10V5 USING [allDescendants, Control, ControlSequence, ControlSequenceObject, Direction, Filter, FilterObject, FilterType, PatternFilter, RelationFilter, Scope, ScopeObject, ScopeSequence, ScopeSequenceObject, ScopeType, unlimitedCount],
RefText USING [InlineAppendChar, ObtainScratch],
Rope USING [FromProc, InlineFetch, Length, ROPE],
XNSFilingAttributes USING [Interpreted, InterpretedRange];
XNSFilingAttributeImpl: CEDAR MONITOR
IMPORTS BasicTime, RefText, Rope
EXPORTS XNSFilingAttributes ~ {
OPEN FilingP10V5, FilingAttributesP10V5, XNSFilingAttributes;
ROPE: TYPE ~ Rope.ROPE;
xx
InfoFromAttributeSequence: PUBLIC PROC [attributes: AttributeSequence]
RETURNS [vers: CARD ← 0, bytes: INT ← -1, created: BasicTime.GMT ← BasicTime.nullGMT, fileType: CARD ← 0, pathName: REF TEXTNIL, fID: FileID ← nullFileID, isDir: BOOLFALSE, numKids: CARD ← 0] ~ {
FOR i: INT IN [0..attributes.length) DO
attribute: Attribute ~ attributes[i];
color: Interpreted;
IF ( attribute.type NOT IN InterpretedRange ) THEN LOOP;
color ← VAL[attribute.type];
SELECT color FROM
createdOn => {
temp: CARD32 ~ DecapsulateCard32[attribute.value];
created ← BasicTime.FromNSTime[temp ! BasicTime.OutOfRange => CONTINUE];
};
numberOfChildren => {
numKids ← 0;
IF ( attribute.value = NIL ) THEN LOOP;
IF ( attribute.value.length = 0 ) THEN LOOP;
numKids ← DecapsulateCard16[attribute.value];
};
dataSize => { bytes ← DecapsulateCard32[attribute.value] };
fileID => { fID ← DecapsulateFileID[attribute.value] };
isDirectory => { isDir ← DecapsulateBoolean[attribute.value] };
pathname => { pathName ← DecapsulateRefText[attribute.value] };
type => { fileType ← DecapsulateCard32[attribute.value] };
version => { vers ← DecapsulateCard16[attribute.value] };
ENDCASE => NULL;
ENDLOOP;
};
Well-known constants
nullAttributes: PUBLIC AttributeSequence ← NEW[AttributeSequenceObject[0]];
nullControls: PUBLIC ControlSequence ← NEW[ControlSequenceObject[0]];
Support things
BuildScope: PUBLIC PROC [filterType: FilterType, rope: ROPE, type: CARD32]
RETURNS [scope: ScopeSequence] = {
value: AttributeValue ← EncapsulateRope[rope];
filter: Filter;
scope ← NEW[ScopeSequenceObject[4]];
scope[0] ← NEW[ScopeObject.count ← [count[unlimitedCount]]];
scope[1] ← NEW[ScopeObject.depth ← [depth[allDescendants]]];
scope[2] ← NEW[ScopeObject.direction ← [direction[forward]]];
filter ← SELECT filterType FROM
matches => NEW [FilterObject.matches ←
[matches[matches: [attribute: [type: type, value: value]]] ]],
equal => NEW [FilterObject.equal ←
[equal[equal: [attribute: [type: type, value: value], interpretation: string]] ]],
ENDCASE => NEW [FilterObject.none ←
[none[none: [null: 0]] ]];
scope[3] ← NEW [ScopeObject.filter ← [filter[filter: filter]]];
};
BuildAttribute: PUBLIC PROC [name: ROPE, type: CARD32,
time: BasicTime.GMT ← BasicTime.nullGMT, timeType: CARD32 ← 0]
RETURNS [attributes: AttributeSequence] = {
IF time = BasicTime.nullGMT THEN {
attributes ← NEW [AttributeSequenceObject[1]];
attributes[0] ← [type: type, value: EncapsulateRope[name]];
RETURN[attributes];
};
attributes ← NEW [AttributeSequenceObject[2]];
attributes[0] ← [type: timeType, value: EncapsulateCard32[BasicTime.ToNSTime[time]]];
attributes[1] ← [type: type, value: EncapsulateRope[name]];
RETURN[attributes];
};
BuildDirectoryAttribute: PUBLIC PROC [nameR: ROPE]
RETURNS [attributes: AttributeSequence] = {
attributes ← NEW [AttributeSequenceObject[3]];
attributes[0] ← [type: Interpreted.isDirectory.ORD, value: EncapsulateBoolean[TRUE]];
attributes[1] ← [type: Interpreted.name.ORD, value: EncapsulateRope[nameR]];
attributes[2] ← [type: Interpreted.type.ORD, value: EncapsulateCard32[1 -- tDirectory --]];
RETURN[attributes];
};
BuildStoreAttributes: PUBLIC PROC [file: ROPE, vers: CARDINAL, created: BasicTime.GMT]
RETURNS [attributes: AttributeSequence] ~ {
num: CARDINALIF ( created = BasicTime.nullGMT ) THEN 2 ELSE 3;
attributes ← NEW [AttributeSequenceObject[num]];
attributes[0] ← [type: Interpreted.name.ORD, value: EncapsulateRope[file]];
attributes[1] ← [type: Interpreted.version.ORD, value: EncapsulateCard16[vers]];
IF ( created # BasicTime.nullGMT ) THEN {
time: CARD32 ← BasicTime.ToNSTime[created];
attributes[2] ← [type: Interpreted.createdOn.ORD, value: EncapsulateCard32[time]];
};
};
Attribute Encapsulation
EncapsulateAccessList: PUBLIC PROC [accessList: AccessList]
RETURNS [value: AttributeValue] ~ {
value ← NIL;
};
DecapsulateAccessList: PUBLIC PROC [value: AttributeValue]
RETURNS [accessList: AccessList] ~ {
GetAccessEntrySequence: PROC [h: CrRPC.Handle, s: CrRPC.STREAM]
RETURNS [res: AccessEntrySequence] ~ {
GetAccess: PROC [h: CrRPC.Handle, s: CrRPC.STREAM]
RETURNS [res: AccessSequence] ~ {
length14: CARDINAL ~ DecapsulateCard16[attribute.value];
interpreted ← NEW[AccessSequenceObject[length14]];
FOR i13: CARDINAL IN [0..length14) DO
res.body[i13] ← VAL[DecapsulateCard16[attribute.value]];
ENDLOOP;
};
length11: CARDINAL ~ DecapsulateCard16[attribute.value];
interpreted ← NEW[AccessEntrySequenceObject[length11]];
FOR i10: CARDINAL IN [0..length11) DO
res.body[i10].key.organization ← DecapsulateRope[attribute.value];
res.body[i10].key.domain ← DecapsulateRope[attribute.value];
res.body[i10].key.object ← DecapsulateRope[attribute.value];
res.body[i10].access ← GetAccess[h, s];
ENDLOOP;
};
accessList.entries ← GetAccessEntrySequence[h, s];
accessList.defaulted ← DecapsulateBoolean[attribute.value];
};
EncapsulateFileID: PUBLIC PROC [fileID: FileID] RETURNS [value: AttributeValue] ~ {
len: CARDINAL ~ 5;
value ← NEW[AttributeValueObject[len]];
FOR i: CARDINAL IN [0..len) DO
value[i] ← fileID[i];
ENDLOOP;
};
DecapsulateFileID: PUBLIC PROC [value: AttributeValue] RETURNS [fileID: FileID] ~ {
IF value = NIL THEN ERROR;
IF value.length # 5 THEN ERROR;
FOR i: CARDINAL IN [0..5) DO
fileID[i] ← value[i];
ENDLOOP;
};
EncapsulateOrdering: PUBLIC PROC [ordering: Ordering]
RETURNS [value: AttributeValue] ~ {
value ← NIL;
};
DecapsulateOrdering: PUBLIC PROC [value: AttributeValue]
RETURNS [ordering: Ordering] ~ {
temp: Basics.LongNumber;
IF value = NIL THEN ERROR;
IF value.length # 4 THEN ERROR;
temp.hi ← value[0];
temp.lo ← value[1];
ordering.key ← temp.lc;
ordering.ascending ← IF value[2] = 1 THEN TRUE ELSE FALSE;
ordering.interpretation ← VAL[value[3]];
};
EncapsulatePosition: PUBLIC PROC [position: Position]
RETURNS [value: AttributeValue] ~ {
value ← NIL;
};
DecapsulatePosition: PUBLIC PROC [value: AttributeValue]
RETURNS [position: Position] ~ {
length: CARDINAL;
IF value = NIL THEN ERROR;
IF value.length <= 0 THEN ERROR;
length ← value[0];
position ← NEW[PositionObject[length]];
FOR i: CARDINAL IN [0..length) DO
position.body[i] ← value[i+1];
ENDLOOP;
};
EncapsulateUser: PUBLIC PROC [name: ROPE] RETURNS [value: AttributeValue] ~ {
value ← NIL;
};
DecapsulateUser: PUBLIC PROC [value: AttributeValue] RETURNS [user: User] ~ {
place: NAT ← 0;
GetRope: PROC [] RETURNS [r: ROPE] = {
temp: Basics.ShortNumber;
len, i: NAT ← 0;
P: PROC RETURNS[c: CHAR] = {
IF i MOD 2 = 0
THEN {temp.sc ← value[place]; place ← place + 1; c ← VAL[temp.hi]}
ELSE {c ← VAL[temp.lo]};
i ← i + 1;
};
len ← value[place];
place ← place + 1;
r ← Rope.FromProc[len: len, p: P];
};
IF value = NIL THEN ERROR;
user.organization ← GetRope[];
user.domain ← GetRope[];
user.object ← GetRope[];
};
Generic (immuatable?)
EncapsulateBoolean: PUBLIC PROC [b: BOOL] RETURNS [value: AttributeValue] ~ {
len: NAT ~ 1; -- wrapped len
value ← NEW [AttributeValueObject[len]];
value[0] ← IF b THEN 1 ELSE 0;
};
DecapsulateBoolean: PUBLIC PROC [value: AttributeValue] RETURNS [b: BOOL] ~ {
IF value = NIL THEN ERROR;
IF value.length # 1 THEN ERROR;
b ← IF value[0] = 1 THEN TRUE ELSE FALSE;
};
EncapsulateCard16: PUBLIC PROC [i: CARD16] RETURNS [value: AttributeValue] ~ {
len: NAT ~ 1; -- wrapped len
value ← NEW [AttributeValueObject[len]];
value[0] ← i;
};
DecapsulateCard16: PUBLIC PROC [value: AttributeValue] RETURNS [i: CARD16] ~ {
IF value = NIL THEN ERROR;
IF value.length # 1 THEN ERROR;
i ← value[0];
};
EncapsulateCard32: PUBLIC PROC [i: CARD32] RETURNS [value: AttributeValue] ~ {
temp: Basics.LongNumber;
len: NAT ~ 2; -- wrapped len
value ← NEW [AttributeValueObject[len]];
temp.lc ← i;
value[0] ← temp.hi;
value[1] ← temp.lo;
};
DecapsulateCard32: PUBLIC PROC [value: AttributeValue] RETURNS [i: CARD32] ~ {
temp: Basics.LongNumber;
IF value = NIL THEN ERROR;
IF value.length # 2 THEN ERROR;
temp.hi ← value[0];
temp.lo ← value[1];
i ← temp.lc;
};
EncapsulateRope: PUBLIC PROC [name: ROPE] RETURNS [value: AttributeValue] ~ {
len: NAT ~ (name.Length[]+3) / 2; -- wrapped len
value ← NEW[AttributeValueObject[len]];
TRUSTED { EncapsulateBytes[@(value.body), name] };
};
DecapsulateRope: PUBLIC PROC [value: AttributeValue] RETURNS [rope: ROPE] ~ {
place: NAT ← 0;
GetRope: PROC [] RETURNS [r: ROPE] = {
temp: Basics.ShortNumber;
len, i: NAT ← 0;
P: PROC RETURNS[c: CHAR] = {
IF i MOD 2 = 0
THEN {temp.sc ← value[place]; place ← place + 1; c ← VAL[temp.hi]}
ELSE {c ← VAL[temp.lo]};
i ← i + 1;
};
len ← value[place];
place ← place + 1;
r ← Rope.FromProc[len: len, p: P];
};
IF value = NIL THEN ERROR;
rope ← GetRope[];
};
DecapsulateRefText: PUBLIC PROC [value: AttributeValue] RETURNS [rope: REF TEXT] ~ {
place: NAT ← 0;
GetRope: PROC [] RETURNS [r: REF TEXT] = {
temp: Basics.ShortNumber;
len: NAT ← 0;
P: PROC [i: NAT] RETURNS[c: CHAR] = {
IF i MOD 2 = 0
THEN {temp.sc ← value[place]; place ← place + 1; c ← VAL[temp.hi]}
ELSE {c ← VAL[temp.lo]};
};
len ← value[place];
place ← place + 1;
r ← RefText.ObtainScratch[len];
FOR i: NAT IN [0 .. len) DO
c: CHAR ~ P[i];
r ← RefText.InlineAppendChar[r, c];
ENDLOOP;
};
IF value = NIL THEN ERROR;
rope ← GetRope[];
};
OpaqueByteObject: TYPE ~ MACHINE DEPENDENT RECORD [
length: CARDINAL,
textLength: CARD16, -- first two bytes of body!
body: PACKED ARRAY [0..1000) OF CHAR
];
EncapsulateBytes: PUBLIC PROC [bytes: LONG POINTER, rope: ROPE] ~ TRUSTED {
len: NAT ~ rope.Length[];
b: LONG POINTER TO OpaqueByteObject ~ bytes;
avo: LONG POINTER TO AttributeValueObject ~ bytes;
b.sequenceLength ← len; -- skip sequence length
avo.body[0] ← len;
FOR i: NAT IN [0..len) DO
b.body[i+2] ← rope.InlineFetch[i];
ENDLOOP;
IF ( (len MOD 2) = 1 ) THEN b.body[len+2] ← 0C;
};
EncapsulateNull: PUBLIC PROC RETURNS [value: AttributeValue] ~ {
len: NAT ~ 0; -- wrapped len
value ← NEW [AttributeValueObject[len]];
};
xx
<<
AllInterpretedValues: TYPE ~ REF AllInterpretedValuesRep;
AllInterpretedValuesRep: TYPE ~ RECORD [
set: PACKED ARRAY Interpreted OF BOOL,
checksum: CARDINAL
];
GetInterpretation: PUBLIC PROC [attribute: Attribute, old: AllInterpretedValues ← NIL]
RETURNS [new: AllInterpretedValues] ~ {
IF old # NIL
THEN new ← old
ELSE { new ← NEW[AllInterpretedValuesRep]; new.set ← ALL[FALSE] };
IF ( attribute.type IN InterpretedRange ) THEN {
color: Interpreted ~ VAL[attribute.type];
new.set[color] ← TRUE;
SELECT color FROM
checksum => { new.checksum ←
DecapsulateCard16[attribute.value]; };
childrenUniquelyNamed => { new.childrenUniquelyNamed ←
DecapsulateBoolean[attribute.value] };
createdBy => { new.createdBy ←
DecapsulateUser[attribute.value] };
createdOn => { new.createdOn ←
DecapsulateCard32[attribute.value] };
fileID => { new.fileID ←
DecapsulateFileID[attribute.value] };
isDirectory => { new.isDirectory ←
DecapsulateBoolean[attribute.value] };
isTemporary => { new.isTemporary ←
DecapsulateBoolean[attribute.value] };
modifiedBy => { new.modifiedBy ←
DecapsulateUser[attribute.value] };
modifiedOn => { new.modifiedOn ←
DecapsulateCard32[attribute.value] };
name => { new.name ←
DecapsulateRope[attribute.value] };
numberOfChildren => { new.numberOfChildren ←
DecapsulateCard16[attribute.value] };
ordering => { new.ordering ←
DecapsulateOrdering[attribute.value] };
parentID => { new.parentID ←
DecapsulateFileID[attribute.value] };
position => { new.position ←
DecapsulatePosition[attribute.value] };
readBy => { new.readBy ←
DecapsulateUser[attribute.value] };
readOn => { new.readOn ←
DecapsulateCard32[attribute.value] };
dataSize => { new.dataSize ←
DecapsulateCard32[attribute.value] };
type => { new.type ←
DecapsulateCard32[attribute.value] };
version => { new.version ←
DecapsulateCard16[attribute.value] };
accessList => { new.accessList ←
DecapsulateAccessList[attribute.value] };
defaultAccessList => { new.defaultAccessList ←
DecapsulateAccessList[attribute.value] };
pathname => { new.pathname ←
DecapsulateRope[attribute.value] };
storedSize => { new.storedSize ←
DecapsulateCard32[attribute.value] };
subtreeSize => { new.subtreeSize ←
DecapsulateCard32[attribute.value] };
subtreeSizeLimit => { new.subtreeSizeLimit ←
DecapsulateCard32[attribute.value] };
ENDCASE => ERROR;
};
};
>>
}.