!fnbits.bsi - Various bit field functions (set, clr, toggle, test) !------------------------------------------------------------------------------------- !VEDIT=100 ![100] April 21, 2009 12:20 AM Edited by jacques ! Created !------------------------------------------------------------------------------------- !Function List: ! Fn'BitSet$(bitfield,bitno) - Set a bit ! Fn'BitClr$(bitfield,bitno) - Clr a bit ! Fn'BitToggle$(bitfield,bitno) - Toggle a bit ! Fn'BitIsSet(bitfield,bitno) - Test a bit !------------------------------------------------------------------------------------- !Notes: ! All of these functions work on "bit fields", which are just unformatted (X) ! variables. The bit numbers are just the linear it position (1..n where n=8x, where ! x is the size of the unformatted var in bytes). ! Most functions (those with $) return the updated bit field. ! ! Although there is no inherent limit to the length of a bit field, well define ! a symbol to set an arbitrary limit at 16 bytes (128 bits) !------------------------------------------------------------------------------------- define MAX_BIT_FIELD = 16 ! max # of bytes in a bit field (arbitrary) define ALL_BITS = 0 ! bit # symbol representing all bits ! NOTE: although it would be preferable to use MAX_BIT_FIELD when specifying the ! bit field sizes in the function parameter definitions, the feature didn't work ! at all prior to 1145, and didn't work completely until 1146.1; so for backwards ! compatibility we'll just hard code the 16 !------------------------------------------------------------------------------------- ! Function : Fn'BitSet$(bitfield,bitno) ! Set a bit in a bit field ! Params: ! bitfield [x, in] bit field ! bitno [b2, in] bit # to set (1 is first, 8 x sizeof bitfield is last) ! if omitted, or ALL_BITS (0), set them all ! Returns: ! Updated bit field ! Notes: ! If bit # out of range do nothing !------------------------------------------------------------------------------------- Function Fn'BitSet$(bitfield as x16, bitno as b2) as x16 map1 locals map2 byteno,b,2 if bitno = ALL_BITS then ! set all bits... Fn'BitSet$ = fill$(chr(255),sizeof(bitfield)) else ! (determine byte # that bitno appears in) byteno = (bitno-1)/8 + 1 ! assuming bit #1 is first ! long but clear approach to extracting/setting bit ... ! (convert bitno into a bit mask) ! bitmask = 2 ^((bitno-1) mod 8) ! bitmask = 0,1,2,4,8,16,32,64,128 ! (extract the byte from the field,) ! btemp = asc(bitfield[byteno;1]) ! (set the bit,) ! btemp = btemp or bitmask ! (put it back) ! bitfield[byteno;1] = chr(btemp) ! short way... (see above for clarification of logic) bitfield[byteno;1] = chr(asc(bitfield[byteno;1]) or (2 ^((bitno-1) mod 8))) ! and return new bit field as func value Fn'BitSet$ = bitfield endif End Function !------------------------------------------------------------------------------------- ! Function : Fn'BitClr$(bitfield,bitno) ! Clear a bit in a bit field ! Params: ! bitfield [x, in] bit field ! bitno [b2, in] bit # to clear (1 is first, 8 x sizeof bitfield is last) ! if omitted, or ALL_BITS (0), clear them all ! Returns: ! Updated bit field ! Notes: ! If bit # out of range do nothing !------------------------------------------------------------------------------------- Function Fn'BitClr$(bitfield as x16, bitno as b2) as x16 map1 locals map2 byteno,b,2 if bitno = ALL_BITS then ! nothing to do since return value starts all clear else ! determine byte # that bitno appears in byteno = (bitno-1)/8 + 1 ! assuming bit #1 is first ! clear the bit (see Fn'SetBit$() above for clarification of logic) bitfield[byteno;1] = chr(asc(bitfield[byteno;1]) and not (2 ^((bitno-1) mod 8))) ! and return new bit field as func value Fn'BitClr$ = bitfield endif End Function !------------------------------------------------------------------------------------- ! Function : Fn'BitToggle$(bitfield,bitno) ! Toggle a bit in a bit field ! Params: ! bitfield [x, in] bit field ! bitno [b2, in] bit # to toggle (1 is first, 8 x sizeof bitfield is last) ! if omitted, or ALL_BITS (0), toggle them all ! Returns: ! Updated bit field ! Notes: ! If bit # out of range do nothing !------------------------------------------------------------------------------------- Function Fn'BitToggle$(bitfield as x16, bitno as b2) as x16 map1 locals map2 btemp,b,1 map2 byteno,b,2 map2 i,i,2 if bitno = ALL_BITS then ! toggle every bit using XOR on byte-by-byte basis for i = 1 to sizeof(bitfield) btemp = asc(bitfield[i;1]) xor 255 bitfield[i;1] = chr(btemp) next i else ! determine byte # that bitno appears in byteno = (bitno-1)/8 + 1 ! assuming bit #1 is first ! toggle the bit (see Fn'SetBit$() above for clarification of logic) bitfield[byteno;1] = chr(asc(bitfield[byteno;1]) xor (2 ^((bitno-1) mod 8))) endif ! and return new bit field as func value Fn'BitToggle$ = bitfield End Function !------------------------------------------------------------------------------------- ! Function : Test if a bit in a bitfield is set ! Params: ! bitfield [x, in] bit field ! bitno [b2, in] bit # to test (1 is first, 8 x sizeof bitfield is last) ! if omitted, or ALL_BITS (0), test if any are set ! Returns: ! 0 = not set, else set ! Notes: ! If bit # out of range return 0 !------------------------------------------------------------------------------------- Function Fn'BitIsSet(bitfield as x MAX_BIT_FIELD, bitno as b2) as b1 map1 locals map2 byteno,b,2 map2 i,i,2 if bitno = ALL_BITS then ! scan bytes until end or first non-zero for i = 1 to sizeof(bitfield) if asc(bitfield[i;1]) # 0 then Fn'BitIsSet = 1 exit endif next i else ! determine byte # that bitno appears in byteno = (bitno-1)/8 + 1 ! assuming bit #1 is first ! test it and return result (see Fn'SetBit$() above for clarification of logic) Fn'BitIsSet = asc(bitfield[((bitno-1)/8 + 1);1]) and (2 ^((bitno-1) mod 8)) endif End Function