YggBitsImpl.mesa
Copyright Ó 1988 by Xerox Corporation. All rights reserved.
Bob Hagmann February 14, 1989 11:18:07 am PST
DIRECTORY
PBasics USING [ByteBlt, charsPerWord, RawBytes, UnsafeBlock],
Rope USING [ROPE],
YggRep USING [Bits, BitsRep];
Exported procedures
BytesFromBits:
PUBLIC
PROC [bits: YggRep.Bits, startByte:
CARD, block: PBasics.UnsafeBlock] ~ {
Fetch some bytes from an "uninterpreted bytes" object
WITH bits
SELECT
FROM
rBits:
REF YggRep.BitsRep =>
TRUSTED {
nBytes: CARD;
IF startByte >= rBits.validBytes THEN ERROR;
IF rBits.validBytes < startByte + CARD[block.count] THEN ERROR;
nBytes ← PBasics.ByteBlt[
from: [blockPointer: LOOPHOLE[rBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: startByte, stopIndexPlusOne: startByte+block.count],
to: [blockPointer: LOOPHOLE[block.base], startIndex: block.startIndex, stopIndexPlusOne: block.startIndex + block.count]
];
IF nBytes # CARD[block.count] THEN ERROR;
};
ENDCASE => ERROR;
};
BitsFromBits:
PUBLIC
PROC [bits: YggRep.Bits]
RETURNS [copy: YggRep.Bits] ~ {
Fetch some bytes from an "uninterpreted bytes" object
IF bits = NIL THEN RETURN[NIL];
WITH bits
SELECT
FROM
rBits:
REF YggRep.BitsRep =>
TRUSTED {
bitsCopy: REF YggRep.BitsRep;
IF rBits.length < rBits.validBytes THEN ERROR;
copy ← bitsCopy ← NEW[YggRep.BitsRep[rBits.length]];
TRUSTED {
nBytes: CARD;
nBytes ← PBasics.ByteBlt[
from: [blockPointer: LOOPHOLE[rBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: rBits.validBytes],
to: [blockPointer: LOOPHOLE[bitsCopy, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: rBits.validBytes]
];
IF nBytes # rBits.validBytes THEN ERROR;
bitsCopy.validBytes ← rBits.validBytes;
};
};
ENDCASE => ERROR;
};
SizeOfBits:
PUBLIC
PROC [bits: YggRep.Bits]
RETURNS [size:
CARD] ~ {
Size in bytes of an "uninterpreted bytes" object.
IF bits = NIL THEN RETURN[0];
WITH bits
SELECT
FROM
rBits:
REF YggRep.BitsRep => {
RETURN[rBits.validBytes];
};
ENDCASE => ERROR;
};
SetSizeOfBits:
PUBLIC
PROC [bits: YggRep.Bits, size:
CARD]
RETURNS [newRef:
BOOL ← FALSE, newBits: YggRep.Bits ← NIL] ~ {
Set the size in bytes of an "uninterpreted bytes" object. If this grows the object, the new bytes are uninitalized. This may grow the object and change its representation. All callers must look at the newRef and newBits return values. If newRef is TRUE, then the old bits object is no longer valid. The caller is responsible for updating the data structure from which it obtained the bits.
IF bits =
NIL
THEN {
wordLen: INT;
newBitsR: REF YggRep.BitsRep;
newRef ← TRUE;
wordLen ← (((size + PBasics.charsPerWord) - 1)/PBasics.charsPerWord); -- round up to words
newBitsR ← newBits ← NEW[YggRep.BitsRep[PBasics.charsPerWord * wordLen]];
newBitsR.validBytes ← size;
RETURN[TRUE, newBits];
};
WITH bits
SELECT
FROM
rBits: REF YggRep.BitsRep => {
wordLen: INT;
newBitsR: REF YggRep.BitsRep;
IF size <= rBits.length THEN {rBits.validBytes ← size; RETURN [FALSE, NIL]; };
wordLen ← (((size + PBasics.charsPerWord) - 1)/PBasics.charsPerWord); -- round up to words
wordLen ← IF wordLen < 20 THEN wordLen ← wordLen + 1 ELSE wordLen + wordLen/20;
newBitsR ← newBits ← NEW[YggRep.BitsRep[PBasics.charsPerWord * wordLen]];
TRUSTED {
nBytes: CARD;
nBytes ← PBasics.ByteBlt[
from: [blockPointer: LOOPHOLE[rBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: rBits.validBytes],
to: [blockPointer: LOOPHOLE[newBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: rBits.validBytes]
];
IF nBytes # rBits.validBytes THEN ERROR;
newBitsR.validBytes ← size;
};
RETURN[TRUE, newBits];
};
ENDCASE => ERROR;
};
BytesToBits:
PUBLIC
PROC [bits: YggRep.Bits, startByte:
CARD, block: PBasics.UnsafeBlock]
RETURNS [newRef:
BOOL ←
FALSE, newBits: YggRep.Bits ←
NIL] ~ {
Store some bytes into an uninterpreted bytes" object. This may grow the object and change its representation. All callers must look at the newRef and newBits return values. If newRef is TRUE, then the old bits object is no longer valid. The caller is responsible for updating the data structure from which it obtained the bits.
IF bits =
NIL
THEN {
nBits: REF YggRep.BitsRep ← NIL;
wordLen: INT;
wordLen ← ((startByte + CARD[block.count] - 1 + PBasics.charsPerWord)/PBasics.charsPerWord); -- round up to words
wordLen ← IF wordLen < 20 THEN wordLen ← wordLen + 1 ELSE wordLen + wordLen/20;
nBits ← NEW[YggRep.BitsRep[PBasics.charsPerWord * wordLen]];
TRUSTED {
nBytes: CARD;
nBytes ← PBasics.ByteBlt[
from: [blockPointer: block.base, startIndex: block.startIndex, stopIndexPlusOne: block.startIndex + block.count],
to: [blockPointer: LOOPHOLE[nBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: startByte, stopIndexPlusOne: startByte + block.count]
];
IF INT[nBytes] # block.count THEN ERROR;
nBits.validBytes ← startByte + block.count;
};
RETURN[TRUE, nBits];
};
WITH bits
SELECT
FROM
rBits:
REF YggRep.BitsRep => {
IF startByte +
CARD[block.count] <= rBits.length
THEN {
-- it fits in the current object
nBytes: INT;
TRUSTED {nBytes ← PBasics.ByteBlt[
from: [blockPointer: LOOPHOLE[block.base], startIndex: block.startIndex, stopIndexPlusOne: block.startIndex + block.count],
to: [blockPointer: LOOPHOLE[rBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: startByte, stopIndexPlusOne: startByte + block.count]
]; };
IF nBytes # block.count THEN ERROR;
rBits.validBytes ← MAX[rBits.validBytes, startByte + CARD[block.count]];
RETURN[FALSE, NIL];
}
ELSE {
nBits: REF YggRep.BitsRep ← NIL;
wordLen: INT;
wordLen ← ((startByte + CARD[block.count] - 1 + PBasics.charsPerWord)/PBasics.charsPerWord); -- round up to words
wordLen ← IF wordLen < 20 THEN wordLen ← wordLen + 1 ELSE wordLen + wordLen/20;
nBits ← NEW[YggRep.BitsRep[PBasics.charsPerWord * wordLen]];
TRUSTED {
nBytes: CARD;
nBytes ← PBasics.ByteBlt[
from: [blockPointer: LOOPHOLE[rBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: rBits.validBytes],
to: [blockPointer: LOOPHOLE[nBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: 0, stopIndexPlusOne: rBits.validBytes]
];
IF nBytes # rBits.validBytes THEN ERROR;
nBytes ← PBasics.ByteBlt[
from: [blockPointer: block.base, startIndex: block.startIndex, stopIndexPlusOne: block.startIndex + block.count],
to: [blockPointer: LOOPHOLE[nBits, LONG POINTER] + SIZE[YggRep.BitsRep[0]], startIndex: startByte, stopIndexPlusOne: startByte + block.count]
];
IF INT[nBytes] # block.count THEN ERROR;
nBits.validBytes ← startByte + block.count;
};
RETURN[TRUE, nBits];
};
};
ENDCASE => ERROR;
};