searchNodes($ip); } private function resolveStartingNode($type) { $node = $this->getNodeReader()->read(0); if ($type === IpAddress::TYPE_IPV4 && $this->metadata->getIpVersion() === IpAddress::TYPE_IPV6) { $skippedBits = (IpAddress::LENGTH_IPV6 - IpAddress::LENGTH_IPV4) * 8; while ($skippedBits-- > 0) { $record = $node->getLeft(); if ($record->isNodePointer()) { $node = $record->getNextNode(); } else { return $record; } } } return $node; } private function getStartingNode($type) { if (!array_key_exists($type, $this->startingNodes)) { $this->startingNodes[$type] = $this->resolveStartingNode($type); } return $this->startingNodes[$type]; } private function searchNodes($ip) { $key = $ip->getBinary(); $byteCount = strlen($key); $nodeReader = $this->getNodeReader(); $node = $this->getStartingNode($ip->getType()); $bits = ''; $record = null; if ($node instanceof Node) { for ($byteIndex = 0; $byteIndex < $byteCount; $byteIndex++) { $byte = ord($key[$byteIndex]); for ($bitOffset = 7; $bitOffset >= 0; $bitOffset--) { $bit = ($byte >> $bitOffset) & 1; $record = $node->getRecord($bit); if ($record->isNodePointer()) { $node = $record->getNextNode(); } else { break 2; } } } } else { $record = $node; } if ($record->isNullPointer()) { return null; } elseif ($record->isDataPointer()) { $this->handle->seek($record->getDataAddress(), SEEK_SET); $data = $this->getDataSectionParser()->parseField(); return $data; } else { return null; } } /** * Open the MMDB file at the given path * @param string $path the path of an MMDB file * @throws IoException if unable to open the file at the provided path * @throws MmdbThrowable if an error occurs while initializing the database */ public static function open($path) { $handle = fopen($path, 'rb'); if ($handle === false) throw new IoException("Unable to open MMDB file at {$path}"); return new self($handle, true); } }