Search code examples
vb6performanceip-addressbit-manipulationcidr

VB6 IP4 - Calculate Net Mask (Long) from Number of Bits


Given input of 0 to 32, representing the number of one-bits in an IP4 network mask (corresponding to a CIDR block size as in /19), what's

  1. An elegant way to turn that into a four-byte long net mask
  2. A fast way way to turn that into a four-byte long net mask

Prototype:

Function NetMaskFromBitCount(BitCount As Long) As Long
   'Logic here '
End Function

Notice this is complicated by the fact that VB6 doesn't do unsigned, so regular math tricks often don't work. If (Number And &H80000000) is nonzero, then Number \ 2 will NOT be the same as a SHR operation.

I've come up with a few ways, but I don't think they're elegant, and they're probably not that fast.

One idea I had is to strategically use the CopyMemory API, which is VERY fast. I've solved some signed/unsigned Long problems in the past by just blatting the Long into a Byte(0 To 3) and working with each portion as needed.

Since I'm also working with the inet_ntoa() and inet_addr() Windows API functions and they return the IP serial number in reverse byte order, a solution that returns the bytes in reverse order is great (I already have a function to flip the byte order if needed, but avoiding it would be nice, too).

Examples:

Input = 2
Output = -1073741824 (&HC0000000)
Alternate Output = 12 (&HC0, reverse byte order)

Input = 19
Output = -8192  (&HFFFFE000)
Alternate Output = 14745599 (&H00E0FFFF, reverse byte order)

Working solutions are good, but ELEGANT or FAST is what I'm looking for.


Solution

  • Function NetMaskFromBitCount(ByVal lBitCount As Long) As Long
        If lBitCount > 0 Then
            NetMaskFromBitCount = -1 * 2 ^ (32 - lBitCount)
        End If
    End Function
    

    Had to make this param ByVal!

    And the test goes here:

    Debug.Assert NetMaskFromBitCount(19) = &HFFFFE000
    Debug.Assert NetMaskFromBitCount(2) = &HC0000000
    Debug.Assert NetMaskFromBitCount(32) = &HFFFFFFFF
    Debug.Assert NetMaskFromBitCount(0) = 0