KNOWLEDGE BASE
Log In    |    Knowledge Base    |    4D Home
Tech Tip: Convert an IP Address string to a Longint
PRODUCT: 4D Server | VERSION: 11.5 | PLATFORM: Mac & Win
Published On: February 19, 2010

Efficient storage of IP addresses can save a lot of disk and memory space while at the same time increasing query performance. Also it enables you to further process data based on subnets and network ranges.

Any IPv4 address can be represented by 32 bits. The “dotted-decimal notation” – which is the most widely known format – is just one form of writing the four bytes separated by dots. In this string representation, an IP address will consist of 7 (x.x.x.x) to 15 (xxx.xxx.xxx.xxx) characters. When encoded with an 8-bit character set (such as UNICODE), the storage space required is therefore at least 15 bytes, in contrast to 4 bytes for the binary representation. In 4D v11 SQL, storing a table with a longint field requires about 4 bytes of storage per record, whereas storing an IP address in C_STRING(15;StrVar) or VARCHAR(15) format requires three to four times as much.

Besides saving space, storing in binary format will also allow for more efficient and smaller indexing, and hence result in faster lookup times. Even with the database doing the string-to-numeric conversion, it is 9% to 12% faster to store IP addresses as long integers, rather than strings.

As an added benefit, the binary representation enables the performance of searches based on subnets and arbitrary network ranges which is very difficult and slow when using dotted-decimal notation. You can find a real-life example in this subject at Geolocation of IP Addresses.

Once you have the IP address in its string format you need to convert it. Below is a 4D function to convert and IP address from dot format to IP number format (a Longint in 4D).

If (True)
   If (False)
      `*****************************************************************************
      `//
      `// INET_AddressToLongInt
      `//
      `// Purpose: Convert an IP address string into a Long Integer
      `//
      `// $0 - LONGINT - The IP address as a longint
      `// $1 - STRING - A valid IP address in the pattern
      `//
      `*****************************************************************************

   End if
   C_TEXT($MethodName_T)
   $MethodName_T:=Current method name
   `=====================   Declare Variables   ==================================
   `method_parameters_declarations

   C_LONGINT($0;$AddressAsLong_L)
   C_STRING(15;$IPAddress_A15;$1)
   `--------------------------------------------------------------------------------
   `method_wide_constants_declarations
   `--------------------------------------------------------------------------------
   `local_variable_declarations

   C_LONGINT($Ndx)
   C_TEXT($IPPat_T;$Str_T)
   C_BOOLEAN($Match_B)
End if
`======================   Initialize and Setup   ================================

$AddressAsLong_L:=0
$IPAddress_A15:=$1
$IPPat_T:="^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.)"
$IPPat_T:=$IPPat_T+"{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"

If (Not(Match regex($IPPat_T;$IPAddress_A15)))
   ALERT($IPAddress_A15+" is not a legal IP address.")
   
Else
   `========================   Method Actions   ==================================
   
   $Ndx:=Position(".";$IPAddress_A15;1)
   $Str_T:=Substring($IPAddress_A15;1;$Ndx-1)
   $AddressAsLong_L:=Num($Str_T)
   
   $IPAddress_A15:=Substring($IPAddress_A15;$Ndx+1)
   $Ndx:=Position(".";$IPAddress_A15;1)
   $Str_T:=Substring($IPAddress_A15;1;$Ndx-1)
   $AddressAsLong_L:=($AddressAsLong_L<<8)+Num($Str_T)
   
   $IPAddress_A15:=Substring($IPAddress_A15;$Ndx+1)
   $Ndx:=Position(".";$IPAddress_A15;1)
   $Str_T:=Substring($IPAddress_A15;1;$Ndx-1)
   $AddressAsLong_L:=($AddressAsLong_L<<8)+Num($Str_T)
   
   $Str_T:=Substring($IPAddress_A15;$Ndx+1)
   $AddressAsLong_L:=($AddressAsLong_L<<8)+Num($Str_T)
   
   `========================   Clean up and Exit   =================================
End if

$0:=$AddressAsLong_L