Using an Integer to Store Bits
Background
Normally MapInfo uses 1 byte per logical field, this is normal for a database. I have a situation where I want to be able to maintain a number of logical fields, but using a Logical column would create a large number of columns. The following functions allow you to use a 4-byte integer to store up to 32 bit-sized logical fields.
NOTES:
All bits are numbered from right to left starting at 1.
Current only handles 31 Bits (not sure how I can easily and safely check the 32nd bit). See Testing Bits in Signed Integers for the answer.
GetBit
This is a function that retrieves the status of the required bit. Simply by looping through the value you can establish what bits are set.
' MapBasic Bitwise Operators
Declare Function GetBit(ByVal iVal As Integer, ByVal iBit as Integer) As Logical
' GetBit - Returns True or False Depending on the Status of the Bit
' iVal is the integer containing the bit pattern for checking
' iBit is the integer number of the bit to check
' Bits are Numbered From Right to Left Starting at 1
'REGION ' GetBit Function
FUNCTION GetBit(ByVal iVal As Integer, ByVal iBit as Integer) As Logical
DIM lBits(33) As Logical ' Bits Status
DIM iCnt As Integer ' Loop Counter
' Make Sure Positive Integer
iVal = Abs(iVal)
'REGION ' Loop through testing Bits
iCnt = 33
Do
lBits(iCnt) = False
If iVal >= 2^(iCnt - 1) Then
lBits(iCnt) = True
iVal = iVal - 2^(iCnt - 1)
'Print ":DEBUG :- Bit(" & iCnt & ") = True"
Else
'Print ":DEBUG :- Bit(" & iCnt & ") = False"
End If
iCnt = iCnt - 1
Loop Until iCnt = 0
'ENDREGION
'REGION ' Make Sure iBit is outside the Array
If iBit = 0 Then
iBit = iBit + 1
End If
If iBit > 33 Then
iBit = 33
End If
'ENDREGION
'Return Value
GetBit = lBits(iBit)
END FUNCTION
'ENDREGION
ModifyBit
This function allows you to set the status of any bit. It doesn't check the existing status to see if it need changing, it will just set the bit.
Declare Function ModifyBit(ByVal iVal As Integer, ByVal iBit As Integer, ByVal lState As Logical) As Integer
' ModifyBit - Returns an Integer With the requested bit set.
' iVal is the Input integer to modify
' iBit is the Integer number of the Bit to be changed
' lState is the new Logical state of the bit
'REGION
Function ModifyBit(ByVal iVal As Integer, ByVal iBit As Integer, ByVal lState As Logical) As Integer
DIM lBits(33) As Logical ' Bits Status
DIM iCnt As Integer ' Loop Counter
' Set Default Value
ModifyBit = 0
' Make Sure Positive Integer
iVal = Abs(iVal)
'REGION ' Loop through testing Bits
iCnt = 33
Do
lBits(iCnt) = False
If iVal >= 2^(iCnt - 1) Then
lBits(iCnt) = True
iVal = iVal - 2^(iCnt - 1)
'Print ":DEBUG :- Bit(" & iCnt & ") = True"
Else
'Print ":DEBUG :- Bit(" & iCnt & ") = False"
End If
iCnt = iCnt - 1
Loop Until iCnt = 0
'ENDREGION
'REGION ' Make Sure iBit is inside the Array
If iBit = 0 Then
iBit = iBit + 1
End If
If iBit > 33 Then
iBit = 33
End If
'ENDREGION
'REGION ' Change iBit Status
lBits(iBit) = lState
'ENDREGION
'REGION 'Calculate New Integer Value (the safe way)
iVal = 0
iCnt = 33
Do
If lBits(iCnt) = True Then
iVal = iVal + (2^(iCnt - 1))
'Print ":DEBUG :- iVal = " & iVal
End If
iCnt = iCnt - 1
Loop Until iCnt = 0
'ENDREGION
' Set Return Value
'Print ":DEBUG :- ModifyBit = " & iVal
ModifyBit = iVal
END FUNCTION
'ENDREGION
| subtopics: |