all the db binary string will be loaded into memory
then search the memory only and this will a lot faster than disk base search
@Note:
invoke it once before put it to public invoke could make it thread safe

@param   $ip
762165
public function memorySearch($ip)
    {
        //check and load the binary string for the first time
        if ( $this->dbBinStr == NULL ) {
            $this->dbBinStr = file_get_contents($this->dbFile);
            if ( $this->dbBinStr == false ) {
                throw new Exception("Fail to open the db file {$this->dbFile}");
            }

            $this->firstIndexPtr = self::getLong($this->dbBinStr, 0);
            $this->lastIndexPtr  = self::getLong($this->dbBinStr, 4);
            $this->totalBlocks   = ($this->lastIndexPtr-$this->firstIndexPtr)/INDEX_BLOCK_LENGTH + 1;
        }

        if ( is_string($ip) ) $ip = self::safeIp2long($ip);

        //binary search to define the data
        $l = 0;
        $h = $this->totalBlocks;
        $dataPtr = 0;
        while ( $l <= $h ) {
            $m = (($l + $h) >> 1);
            $p = $this->firstIndexPtr + $m * INDEX_BLOCK_LENGTH;
            $sip = self::getLong($this->dbBinStr, $p);
            if ( $ip < $sip ) {
                $h = $m - 1;
            } else {
                $eip = self::getLong($this->dbBinStr, $p + 4);
                if ( $ip > $eip ) {
                    $l = $m + 1;
                } else {
                    $dataPtr = self::getLong($this->dbBinStr, $p + 8);
                    break;
                }
            }
        }

        //not matched just stop it here
        if ( $dataPtr == 0 ) return NULL;

        //get the data
        $dataLen = (($dataPtr >> 24) & 0xFF);
        $dataPtr = ($dataPtr & 0x00FFFFFF);

        return array(
            'city_id' => self::getLong($this->dbBinStr, $dataPtr), 
            'region'  => substr($this->dbBinStr, $dataPtr + 4, $dataLen - 4)
        );
    }
5928
public function isISOBlocked($ip){
        return $this->db->select($this->getBlockedISOTable(), ['iso' => $this->getIPCountryISO($ip)]);
    }
302237
public static function safeIp2long($ip) 
    {
        $ip = ip2long($ip);

        // convert signed int to unsigned int if on 32 bit operating system
        if ($ip < 0 && PHP_INT_SIZE == 4) {
            $ip = sprintf("%u", $ip);
        } 

        return $ip;
    }
1256198
public static function isValid(string $ip = null)
    {
        if (is_null($ip)) {
            $ip = self::get();
        }

        return filter_var($ip, FILTER_VALIDATE_IP) == $ip;
    }
582677
public function lookupIp($ip)
    {
        $results = array();

        $continentServer = new Server();
        foreach ($continentServer->getContinentServers() as $server) {
            $result = $this->queryServer($server, $ip);
                if ($result && !in_array($result, $results)) {
                    $results[$server]= $result;
                }
        }
        $res = "RESULTS FOUND: " . count($results);
        foreach ($results as $server => $result) {
            $res .= "Lookup results for " . $ip . " from " . $server . " server: " . $result;
        }
        return $res;
    }
415040
public static function isPrivateIp(string $ip): bool
    {
        foreach (self::PRIVATE_IPV4_RANGES as $range) {
            if (self::isIpInCidr($ip, $range)) {
                return true;
            }
        }

        return false;
    }
842887
private function expandIPv6($ip) {
        // Convert to in_addr an unpack as hex
        $hex = strtolower(bin2hex(inet_pton($ip)));

        // Inject colons
        return substr(preg_replace('/([a-f0-9]{4})/', '$1:', $hex), 0, -1);
    }
1068633
public function btreeSearch( $ip )
    {
        if ( is_string($ip) ) $ip = self::safeIp2long($ip);

        //check and load the header
        if ( $this->HeaderSip == NULL ) {
            //check and open the original db file
            if ( $this->dbFileHandler == NULL ) {
                $this->dbFileHandler = fopen($this->dbFile, 'r');
                if ( $this->dbFileHandler == false ) {
                    throw new Exception("Fail to open the db file {$this->dbFile}");
                }
            }

            fseek($this->dbFileHandler, 8);
            $buffer = fread($this->dbFileHandler, TOTAL_HEADER_LENGTH);
            
            //fill the header
            $idx = 0;
            $this->HeaderSip = array();
            $this->HeaderPtr = array();
            for ( $i = 0; $i < TOTAL_HEADER_LENGTH; $i += 8 ) {
                $startIp = self::getLong($buffer, $i);
                $dataPtr = self::getLong($buffer, $i + 4);
                if ( $dataPtr == 0 ) break;

                $this->HeaderSip[] = $startIp;
                $this->HeaderPtr[] = $dataPtr;
                $idx++;
            }

            $this->headerLen = $idx;
        }
        
        //1. define the index block with the binary search
        $l = 0; $h = $this->headerLen; $sptr = 0; $eptr = 0;
        while ( $l <= $h ) {
            $m = (($l + $h) >> 1);
            
            //perfetc matched, just return it
            if ( $ip == $this->HeaderSip[$m] ) {
                if ( $m > 0 ) {
                    $sptr = $this->HeaderPtr[$m-1];
                    $eptr = $this->HeaderPtr[$m  ];
                } else {
                    $sptr = $this->HeaderPtr[$m ];
                    $eptr = $this->HeaderPtr[$m+1];
                }
                
                break;
            }
            
            //less then the middle value
            if ( $ip < $this->HeaderSip[$m] ) {
                if ( $m == 0 ) {
                    $sptr = $this->HeaderPtr[$m  ];
                    $eptr = $this->HeaderPtr[$m+1];
                    break;
                } else if ( $ip > $this->HeaderSip[$m-1] ) {
                    $sptr = $this->HeaderPtr[$m-1];
                    $eptr = $this->HeaderPtr[$m  ];
                    break;
                }
                $h = $m - 1;
            } else {
                if ( $m == $this->headerLen - 1 ) {
                    $sptr = $this->HeaderPtr[$m-1];
                    $eptr = $this->HeaderPtr[$m  ];
                    break;
                } else if ( $ip <= $this->HeaderSip[$m+1] ) {
                    $sptr = $this->HeaderPtr[$m  ];
                    $eptr = $this->HeaderPtr[$m+1];
                    break;
                }
                $l = $m + 1;
            }
        }
        
        //match nothing just stop it
        if ( $sptr == 0 ) return NULL;
        
        //2. search the index blocks to define the data
        $blockLen = $eptr - $sptr;
        fseek($this->dbFileHandler, $sptr);
        $index = fread($this->dbFileHandler, $blockLen + INDEX_BLOCK_LENGTH);
        
        $dataptr = 0;
        $l = 0; $h = $blockLen / INDEX_BLOCK_LENGTH;
        while ( $l <= $h ) {
            $m = (($l + $h) >> 1);
            $p = (int)($m * INDEX_BLOCK_LENGTH);
            $sip = self::getLong($index, $p);
            if ( $ip < $sip ) {
                $h = $m - 1;
            } else {
                $eip = self::getLong($index, $p + 4);
                if ( $ip > $eip ) {
                    $l = $m + 1;
                } else {
                    $dataptr = self::getLong($index, $p + 8);
                    break;
                }
            }
        }
        
        //not matched
        if ( $dataptr == 0 ) return NULL;
        
        //3. get the data
        $dataLen = (($dataptr >> 24) & 0xFF);
        $dataPtr = ($dataptr & 0x00FFFFFF);
        
        fseek($this->dbFileHandler, $dataPtr);
        $data = fread($this->dbFileHandler, $dataLen);

        return array(
            'city_id' => self::getLong($data, 0), 
            'region'  => substr($data, 4)
        );
    }
347022
public static function validateIp($ip)
    {
        if (strtolower($ip) === 'unknown') {
            return false;
        }
        // generate ipv4 network address
        $ip = ip2long($ip);

        // if the ip is set and not equivalent to 255.255.255.255
        if (($ip !== false) && ($ip !== -1)) {
            // make sure to get unsigned long representation of ip
            // due to discrepancies between 32 and 64 bit OSes and
            // signed numbers (ints default to signed in PHP)
            $ip = sprintf('%u', $ip);
            // do private network range checking
            if ($ip >= 0 && $ip <= 50331647) {
                return false;
            }
            if ($ip >= 167772160 && $ip <= 184549375) {
                return false;
            }
            if ($ip >= 2130706432 && $ip <= 2147483647) {
                return false;
            }
            if ($ip >= 2851995648 && $ip <= 2852061183) {
                return false;
            }
            if ($ip >= 2886729728 && $ip <= 2887778303) {
                return false;
            }
            if ($ip >= 3221225984 && $ip <= 3221226239) {
                return false;
            }
            if ($ip >= 3232235520 && $ip <= 3232301055) {
                return false;
            }
            if ($ip >= 4294967040) {
                return false;
            }
        }
        return true;
    }
378737
public function isAllowed ($ip, $priority = 'deny,allow')
	{
		
		// Convert IP to decimal
		
		$ipDec = (float)sprintf ("%u", ip2long ($ip));
		
		// Check
		
		foreach (explode (',', $priority) as $type)
		{
			
			switch ($type)
			{
				
				// Check if the IP is allowed
				
				case 'allow':
					
					foreach ($this->allowIPs as $name => $range)
					{
						if ($this->isInside ($ipDec, $name, $range))
						{
							return TRUE;
						}
					}
					
					break;
				
				// Check if IP is denied
					
				case 'deny':
					
					foreach ($this->denyIPs as $name => $range)
					{
						if ($this->isInside ($ipDec, $name, $range))
						{
							return FALSE;
						}
					}
					
					break;
				
			}
			
		}
		
		// Not allowed by default
		
		return FALSE;
		
	}
689128
public function validateIp($ip)
    {
        $ipnums = explode(".", $ip);
        if (count($ipnums) != 4) {
            return false;
        }
        foreach($ipnums as $ipnum) {
            if (!is_numeric($ipnum) || ($ipnum > 255)) {
                return false;
            }
        }
        return $ip;
    }
443980
public static function close($ip) {

        return (new Color())->getColoredString(sprintf(self::CLOSE, self::date(), $ip), 'white', 'black').PHP_EOL;

    }
1053291
private function binSearch($version, $ipNumber, $cidr=false) {
    if (false === $version) {
      // unrecognized version
      return false;
    }

    // initialize fields
    $base   = $this->ipBase[$version];
    $offset = $this->offset[$version];
    $width  = $this->columnWidth[$version];
    $high   = $this->ipCount[$version];
    $low    = 0;

	//hjlim
	$indexBaseStart = $this->indexBaseAddr[$version];
	if ($indexBaseStart > 0){
		$indexPos = 0;
		switch($version){
			case 4:
				$ipNum1_2 = intval($ipNumber / 65536);
				$indexPos = $indexBaseStart + ($ipNum1_2 << 3);

				break;

			case 6:
				$ipNum1 = intval(bcdiv($ipNumber, bcpow('2', '112')));
				$indexPos = $indexBaseStart + ($ipNum1 << 3);

				break;

			default:
				return false;
		}

		$low = $this->readWord($indexPos);
		$high = $this->readWord($indexPos + 4);
	}

    // as long as we can narrow down the search...
	while ($low <= $high) {
      $mid     = (int) ($low + (($high - $low) >> 1));

	  // Read IP ranges to get boundaries
      $ip_from = $this->readIp($version, $base + $width * $mid);
      $ip_to   = $this->readIp($version, $base + $width * ($mid + 1));

      // determine whether to return, repeat on the lower half, or repeat on the upper half
      switch (self::ipBetween($version, $ipNumber, $ip_from, $ip_to)) {
        case 0:
          return ($cidr) ? array($ip_from, $ip_to) : $base + $offset + $mid * $width;
        case -1:
          $high = $mid - 1;
          break;
        case 1:
          $low  = $mid + 1;
          break;
      }
    }

    // nothing found
    return false;
  }
1336775
private static function fromInt(int $ip): \GMP
    {
        $ip = gmp_init(sprintf('%u', $ip), 10);
        if (!self::isValid($ip)) {
            throw new \InvalidArgumentException(sprintf('The integer "%s" is not a valid IPv%d address.', gmp_strval($ip), static::IP_VERSION));
        }

        return $ip;
    }
395065
protected function isValidIpAddress($ip)
    {
        $flags = FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6;
        if (filter_var($ip, FILTER_VALIDATE_IP, $flags) === false) {
            return false;
        }
        return true;
    }
572146
public function isIPBlocked($ip){
        return ($this->isIPBlockedList($ip) || $this->isIPBlockedRange($ip) || $this->isISOBlocked($ip));
    }
73235
private function ip2bin($ip)
    {
        if ($this->getIpVersion($ip) === 4) {
            return str_pad(base_convert(ip2long($ip), 10, 2), static::IPV4_ADDRESS_LENGTH, '0', STR_PAD_LEFT);
        } else {
            $unpack = unpack('A16', inet_pton($ip));
            $binStr = array_shift($unpack);
            $bytes = static::IPV6_ADDRESS_LENGTH / 8; // 128 bit / 8 = 16 bytes
            $result = '';
            while ($bytes-- > 0) {
                $result = sprintf('%08b', isset($binStr[$bytes]) ? ord($binStr[$bytes]) : '0') . $result;
            }
            return $result;
        }
    }