--Transport Mechanism Filestore - Bit maps -- -- Randy Gobbel 19-May-81 13:16:21 -- -- A.D.Birrell December 13, 1978 5:09 PM -- DIRECTORY BitMapDefs USING[ MapLevel, Map, MapIndex ], Storage USING[ Node ], Inline USING[ BITSHIFT, BITAND, BITOR, BITNOT ]; BitMap: PROGRAM IMPORTS Inline, Storage EXPORTS BitMapDefs = BEGIN OPEN BitMapDefs, Inline; Allocate: PROCEDURE[CARDINAL]RETURNS[POINTER] = Storage.Node; BitPos: TYPE = [0..16); -- name of a bit in a word -- unset: WORD = 0B; -- all bits 0 -- allSet: WORD = 177777B; -- all bits 1 -- MapFull: ERROR = CODE; FindFree: PUBLIC PROCEDURE[ m: Map ] RETURNS[ MapIndex ] = BEGIN wPos: MapIndex = IF m.level=0 THEN 0 ELSE FindFree[m.next]; word: WORD = m.data[wPos]; -- now find the first 0 bit in 'word' -- -- more efficient not to parameterise by 'width' -- bPos: BitPos ← 0; half: WORD ← BITAND[word,377B]; IF half=377B THEN BEGIN half ← BITSHIFT[word,-8]; bPos ← bPos+8 END; BEGIN quart: WORD ← BITAND[half,17B]; IF quart=17B THEN BEGIN quart ← BITSHIFT[half,-4]; bPos ← bPos+4 END; BEGIN eight: WORD ← BITAND[quart,3B]; IF eight=3B THEN BEGIN eight ← BITSHIFT[quart,-2]; bPos ← bPos+2 END; IF eight=1B THEN bPos ← bPos+1 ELSE IF eight=3B THEN ERROR MapFull[]; END; END; RETURN[ BITOR[ BITSHIFT[wPos,4], bPos ] ] END; Set: PUBLIC PROCEDURE[ m: Map, pos: MapIndex ] = BEGIN wPos: MapIndex = BITSHIFT[pos,-4]; word: POINTER TO WORD = @(m.data[wPos]); word↑ ← BITOR[ word↑, BITSHIFT[ 1B, BITAND[pos,17B] ] ]; IF word↑ = allSet AND m.level # 0 THEN Set[m.next, wPos]; END; Test: PUBLIC PROCEDURE[ m: Map, pos: MapIndex ] RETURNS[ BOOLEAN ] = BEGIN wPos: MapIndex = BITSHIFT[pos,-4]; RETURN[ IF wPos >= LENGTH[m.data] THEN FALSE ELSE BITAND[ m.data[wPos], BITSHIFT[1B,BITAND[pos,17B]] ] # 0 ] END; Clear: PUBLIC PROCEDURE[ m: Map, pos: MapIndex ] = BEGIN wPos: MapIndex = BITSHIFT[pos,-4]; word: POINTER TO WORD = @(m.data[wPos]); bPos: BitPos = BITAND[pos,17B]; IF word↑ = allSet AND m.level # 0 THEN Clear[m.next, wPos]; word↑ ← BITAND[ word↑, BITNOT[BITSHIFT[1B,bPos]] ]; END; Create: PUBLIC PROCEDURE[ size: CARDINAL ] RETURNS[ m: Map ] = BEGIN -- beware of overflow if size = LAST[CARDINAL] -- words: CARDINAL = size/16 + (IF size MOD 16 = 0 THEN 0 ELSE 1); m ← Allocate[SIZE[MapLevel]]; m.data ← DESCRIPTOR[ Allocate[words], words ]; BEGIN index: CARDINAL; FOR index IN [0..words) DO m.data[index] ← unset ENDLOOP; END; IF words > 1 THEN BEGIN m.next ← Create[words]; m.level ← m.next.level + 1; END ELSE BEGIN m.next ← NIL --only a safety precaution--; m.level ← 0; END; END; END.