- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在寻找一种 php 算法,它可以有效地测试一个 cidr 标记的网络是否与另一个网络重叠。
基本上我有以下情况:
cidr 地址数组:
$cidrNetworks = array(
'192.168.10.0/24',
'10.10.0.30/20',
etc.
);
我有一个方法可以将网络添加到数组中,但是当添加的网络与数组中已经存在的网络重叠时,该方法应该抛出异常。
即。如果添加了 192.168.10.0/25,则应抛出异常。
有没有人有/知道/“能想到”一种有效测试它的方法?
最佳答案
这是之前在聊天中讨论的类的更新版本。它可以做你需要的,以及许多其他有用的事情。
<?php
class IPv4Subnet implements ArrayAccess, Iterator {
/*
* Address format constants
*/
const ADDRESS_BINARY = 0x01;
const ADDRESS_INT = 0x02;
const ADDRESS_DOTDEC = 0x04;
const ADDRESS_SUBNET = 0x08;
/*
* Constants to control whether getHosts() returns the network/broadcast addresses
*/
const HOSTS_WITH_NETWORK = 0x10;
const HOSTS_WITH_BROADCAST = 0x20;
const HOSTS_ALL = 0x30;
/*
* Properties to store base address and subnet mask as binary strings
*/
protected $address;
protected $mask;
/*
* Counter to track the current iteration offset
*/
private $iteratorOffset = 0;
/*
* Array to hold values retrieved via ArrayAccess
*/
private $arrayAccessObjects = array();
/*
* Helper methods
*/
private function longToBinary ($long) {
return pack('N', $long);
}
private function longToDottedDecimal ($long) {
return ($long >> 24 & 0xFF).'.'.($long >> 16 & 0xFF).'.'.($long >> 8 & 0xFF).'.'.($long & 0xFF);
}
private function longToByteArray ($long) {
return array(
$long >> 24 & 0xFF,
$long >> 16 & 0xFF,
$long >> 8 & 0xFF,
$long & 0xFF
);
}
private function longToSubnet ($long) {
if (!isset($this->arrayAccessObjects[$long])) {
$this->arrayAccessObjects[$long] = new self($long);
}
return $this->arrayAccessObjects[$long];
}
private function binaryToLong ($binary) {
return current(unpack('N', $binary));
}
private function binaryToDottedDecimal ($binary) {
return implode('.', unpack('C*', $binary));
}
private function binaryToX ($binary, $mode) {
if ($mode & self::ADDRESS_BINARY) {
$result = $binary;
} else if ($mode & self::ADDRESS_INT) {
$result = $this->binaryToLong($binary);
} else if ($mode & self::ADDRESS_DOTDEC) {
$result = $this->binaryToDottedDecimal($binary);
} else {
$result = $this->longToSubnet($this->binaryToLong($binary));
}
return $result;
}
private function byteArrayToLong($bytes) {
return ($bytes[0] << 24) | ($bytes[1] << 16) | ($bytes[2] << 8) | $bytes[3];
}
private function byteArrayToBinary($bytes) {
return pack('C*', $bytes[0], $bytes[1], $bytes[2], $bytes[3]);
}
private function normaliseComparisonSubject (&$subject) {
if (!is_object($subject)) {
$subject = new self($subject);
}
if (!($subject instanceof self)) {
throw new InvalidArgumentException('Subject must be an instance of IPv4Subnet');
}
}
private function validateOctetArray (&$octets) {
foreach ($octets as &$octet) {
$octet = (int) $octet;
if ($octet < 0 || $octet > 255) {
return FALSE;
}
}
return TRUE;
}
/*
* Constructor
*/
public function __construct ($address = NULL, $mask = NULL) {
if ($address === NULL || (is_string($address) && trim($address) === '')) {
$address = array(0, 0, 0, 0);
} else if (is_int($address)) {
$address = $this->longToByteArray($address);
} else if (is_string($address)) {
$parts = preg_split('#\s*/\s*#', trim($address), -1, PREG_SPLIT_NO_EMPTY);
if (count($parts) > 2) {
throw new InvalidArgumentException('No usable IP address supplied: Syntax error');
} else if ($parts[0] === '') {
throw new InvalidArgumentException('No usable IP address supplied: IP address empty');
}
if (!empty($parts[1]) && !isset($mask)) {
$mask = $parts[1];
}
$address = preg_split('#\s*\.\s*#', $parts[0], -1, PREG_SPLIT_NO_EMPTY);
} else if (is_array($address)) {
$address = array_values($address);
} else {
throw new InvalidArgumentException('No usable IP address supplied: Value must be a string or an integer');
}
$suppliedAddressOctets = count($address);
$address += array(0, 0, 0, 0);
if ($suppliedAddressOctets > 4) {
throw new InvalidArgumentException('No usable IP address supplied: IP address has more than 4 octets');
} else if (!$this->validateOctetArray($address)) {
throw new InvalidArgumentException('No usable IP address supplied: At least one octet value outside acceptable range 0 - 255');
}
if ($mask === NULL) {
$mask = array_pad(array(), $suppliedAddressOctets, 255) + array(0, 0, 0, 0);
} else if (is_int($mask)) {
$mask = $this->longToByteArray($mask);
} else if (is_string($mask)) {
$mask = preg_split('#\s*\.\s*#', trim($mask), -1, PREG_SPLIT_NO_EMPTY);
switch (count($mask)) {
case 1: // CIDR
$cidr = (int) $mask[0];
if ($cidr === 0) {
// Shifting 32 bits on a 32 bit system doesn't work, so treat this as a special case
$mask = array(0, 0, 0, 0);
} else if ($cidr <= 32) {
// This looks odd, but it's the nicest way I have found to get the 32 least significant bits set in a
// way that works on both 32 and 64 bit platforms
$base = ~((~0 << 16) << 16);
$mask = $this->longToByteArray($base << (32 - $cidr));
} else {
throw new InvalidArgumentException('Supplied mask invalid: CIDR outside acceptable range 0 - 32');
}
break;
case 4: break; // Dotted decimal
default: throw new InvalidArgumentException('Supplied mask invalid: Must be either a full dotted-decimal or a CIDR');
}
} else if (is_array($mask)) {
$mask = array_values($mask);
} else {
throw new InvalidArgumentException('Supplied mask invalid: Type invalid');
}
if (!$this->validateOctetArray($mask)) {
throw new InvalidArgumentException('Supplied mask invalid: At least one octet value outside acceptable range 0 - 255');
}
// Check bits are contiguous from left
// TODO: Improve this mechanism
$asciiBits = sprintf('%032b', $this->byteArrayToLong($mask));
if (strpos(rtrim($asciiBits, '0'), '0') !== FALSE) {
throw new InvalidArgumentException('Supplied mask invalid: Set bits are not contiguous from the most significant bit');
}
$this->mask = $this->byteArrayToBinary($mask);
$this->address = $this->byteArrayToBinary($address) & $this->mask;
}
/*
* ArrayAccess interface methods (read only)
*/
public function offsetExists ($offset) {
if ($offset === 'network' || $offset === 'broadcast') {
return TRUE;
}
$offset = filter_var($offset, FILTER_VALIDATE_INT);
if ($offset === FALSE || $offset < 0) {
return FALSE;
}
return $offset < $this->getHostsCount();
}
public function offsetGet ($offset) {
if (!$this->offsetExists($offset)) {
return NULL;
}
if ($offset === 'network') {
$address = $this->getNetworkAddress(self::ADDRESS_INT);
} else if ($offset === 'broadcast') {
$address = $this->getBroadcastAddress(self::ADDRESS_INT);
} else {
// How much the address needs to be adjusted by to account for network address
$adjustment = (int) ($this->getHostsCount() > 2);
$address = $this->binaryToLong($this->address) + $offset + $adjustment;
}
return $this->longToSubnet($address);
}
public function offsetSet ($offset, $value) {}
public function offsetUnset ($offset) {}
/*
* Iterator interface methods
*/
public function current () {
return $this->offsetGet($this->iteratorOffset);
}
public function key () {
return $this->iteratorOffset;
}
public function next () {
$this->iteratorOffset++;
}
public function rewind () {
$this->iteratorOffset = 0;
}
public function valid () {
return $this->iteratorOffset < $this->getHostsCount();
}
/*
* Data access methods
*/
public function getHosts ($mode = self::ADDRESS_SUBNET) {
// Parse flags and initialise vars
$bin = (bool) ($mode & self::ADDRESS_BINARY);
$int = (bool) ($mode & self::ADDRESS_INT);
$dd = (bool) ($mode & self::ADDRESS_DOTDEC);
$base = $this->binaryToLong($this->address);
$mask = $this->binaryToLong($this->mask);
$hasNwBc = !($mask & 0x03);
$result = array();
// Get network address if requested
if (($mode & self::HOSTS_WITH_NETWORK) && $hasNwBc) {
$result[] = $base;
}
// Get hosts
for ($current = $hasNwBc ? $base + 1 : $base; ($current & $mask) === $base; $current++) {
$result[] = $current;
}
// Remove broadcast address if present and not requested
if ($hasNwBc && !($mode & self::HOSTS_WITH_BROADCAST)) {
array_pop($result);
}
// Convert to the correct type
if ($bin) {
$result = array_map(array($this, 'longToBinary'), $result);
} else if ($dd) {
$result = array_map(array($this, 'longToDottedDecimal'), $result);
} else if (!$int) {
$result = array_map(array($this, 'longToSubnet'), $result);
}
return $result;
}
public function getHostsCount () {
$count = $this->getBroadcastAddress(self::ADDRESS_INT) - $this->getNetworkAddress(self::ADDRESS_INT);
return $count > 2 ? $count - 1 : $count + 1; // Adjust return value to exclude network/broadcast addresses
}
public function getNetworkAddress ($mode = self::ADDRESS_SUBNET) {
return $this->binaryToX($this->address, $mode);
}
public function getBroadcastAddress ($mode = self::ADDRESS_SUBNET) {
return $this->binaryToX($this->address | ~$this->mask, $mode);
}
public function getMask ($mode = self::ADDRESS_DOTDEC) {
return $this->binaryToX($this->mask, $mode);
}
/*
* Stringify methods
*/
public function __toString () {
if ($this->getHostsCount() === 1) {
$result = $this->toDottedDecimal();
} else {
$result = $this->toCIDR();
}
return $result;
}
public function toDottedDecimal () {
$result = $this->getNetworkAddress(self::ADDRESS_DOTDEC);
if ($this->mask !== "\xFF\xFF\xFF\xFF") {
$result .= '/'.$this->getMask(self::ADDRESS_DOTDEC);
}
return $result;
}
public function toCIDR () {
$address = $this->getNetworkAddress(self::ADDRESS_DOTDEC);
$cidr = strlen(trim(sprintf('%b', $this->getMask(self::ADDRESS_INT)), '0')); // TODO: Improve this mechanism
return $address.'/'.$cidr;
}
/*
* Comparison methods
*/
public function contains ($subject) {
$this->normaliseComparisonSubject($subject);
$subjectAddress = $subject->getNetworkAddress(self::ADDRESS_BINARY);
$subjectMask = $subject->getMask(self::ADDRESS_BINARY);
return $this->mask !== $subjectMask && ($this->mask | ($this->mask ^ $subjectMask)) !== $this->mask && ($subjectAddress & $this->mask) === $this->address;
}
public function within ($subject) {
$this->normaliseComparisonSubject($subject);
$subjectAddress = $subject->getNetworkAddress(self::ADDRESS_BINARY);
$subjectMask = $subject->getMask(self::ADDRESS_BINARY);
return $this->mask !== $subjectMask && ($this->mask | ($this->mask ^ $subjectMask)) === $this->mask && ($this->address & $subjectMask) === $subjectAddress;
}
public function equalTo ($subject) {
$this->normaliseComparisonSubject($subject);
return $this->address === $subject->getNetworkAddress(self::ADDRESS_BINARY) && $this->mask === $subject->getMask(self::ADDRESS_BINARY);
}
public function intersect ($subject) {
$this->normaliseComparisonSubject($subject);
return $this->equalTo($subject) || $this->contains($subject) || $this->within($subject);
}
}
为了做你想做的事,这个类提供了4个方法:
contains()
within()
equalTo()
intersect()
这些的示例用法:
// Also accepts dotted decimal mask. The mask may also be passed to the second
// argument. Any valid combination of dotted decimal, CIDR and integers will be
// accepted
$subnet = new IPv4Subnet('192.168.0.0/24');
// These methods will accept a string or another instance
var_dump($subnet->contains('192.168.0.1')); //TRUE
var_dump($subnet->contains('192.168.1.1')); //FALSE
var_dump($subnet->contains('192.168.0.0/16')); //FALSE
var_dump($subnet->within('192.168.0.0/16')); //TRUE
// ...hopefully you get the picture. intersect() returns TRUE if any of the
// other three match.
该类还实现了Iterator
接口(interface),允许您迭代子网中的所有地址。迭代器排除了可以单独检索的网络和广播地址。
例子:
$subnet = new IPv4Subnet('192.168.0.0/28');
echo "Network: ", $subnet->getNetworkAddress(),
"; Broadcast: ", $subnet->getBroadcastAddress(),
"\nHosts:\n";
foreach ($subnet as $host) {
echo $host, "\n";
}
该类还实现了 ArrayAccess
,允许您将其视为数组:
$subnet = new IPv4Subnet('192.168.0.0/28');
echo $subnet['network'], "\n"; // 192.168.0.0
echo $subnet[0], "\n"; // 192.168.0.1
// ...
echo $subnet[13], "\n"; // 192.168.0.14
echo $subnet['broadcast'], "\n"; // 192.168.0.15
注意:访问子网主机地址的迭代器/数组方法将返回另一个 IPv4Subnet
对象。该类实现了 __toString()
,如果它表示单个地址,它将以点分十进制形式返回 IP 地址,如果它表示多个地址,则返回 CIDR。通过调用相关的 get*()
方法并传递所需的标志(请参阅类顶部定义的常量),可以将数据作为字符串或整数直接访问。
所有操作都是 32 位和 64 位安全的。兼容性应该是(虽然没有彻底测试)5.2+
为了完整起见,我想您的用例将按照以下方式实现:
public function addSubnet ($newSubnet) {
$newSubnet = new IPv4Subnet($newSubnet);
foreach ($this->subnets as &$existingSubnet) {
if ($existingSubnet->contains($newSubnet)) {
throw new Exception('Subnet already added');
} else if ($existingSubnet->within($newSubnet)) {
$existingSubnet = $newSubnet;
return;
}
}
$this->subnets[] = $newSubnet;
}
关于php - 测试 cidr 表示法中的网络是否与另一个网络重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13608394/
我对具有 2 个轴的数据有交叉识别问题,例如 A = array([['x0', 'y0', 'data0', 'data0'], ['x0', 'y0', 'data0', '
我知道这是代码有点傻,但有人可以解释为什么 isList [42]返回 True而isList2 [42]打印 False ,以及如何防止这种情况?我想更好地理解一些更晦涩的 GHC 类型扩展,我认为
我正在使用memmove(),但目标似乎正在覆盖源,或者也许我不明白覆盖是什么。我有一个 char 数组(目标),然后是一个指向目标的指针,该指针位于 vector 内部。 char destinat
以下AS3代码有时会导致音频多次播放,就像疯狂的回声一样,几乎同时播放。通常使用该URL都可以,但是当我使用https://soundcloud.com url时,它总是会发疯。在极少数情况下,我认为
我正在尝试在 android 2.2 中实现类似操作栏的东西。这是我的 main.xml
如何避免第一个值的重叠问题 而且,我怎样才能看到最后一个被剪裁的值? 最佳答案 我认为您在修改轴上的样式和调整视口(viewport)之间有几种选择。 我会尝试: 禁用左轴,启用右轴 chart.le
我正在构建一个简单的应用程序,您可以在其中使用纸娃娃之类的工具来描述您的外观。 Check out this image.计划是有 4 个水平 ScrollView :第一个用于发型,第二个用于面部毛
我有一个问题...我在绝对布局中有两个 ScrollView 。换句话说,它们是全屏的并且相互重叠 上面的scrollview是水平滚动的,下面的是垂直滚动的scrollview。 当我水平滚动时,我
我看了一些类似的问题,但我不太明白在我的层次结构中我应该做什么? 我有 用于屏幕底部的标签菜单 和 对于其他将创建的 fragment 。 我有 9 个标签菜单,每个都是 fragment 。 一
在我的 Android 应用程序中,我有一个编辑文本和一个按钮,单击该按钮会向我的主要 Activity 添加一个 fragment ,其中包含在我的编辑文本中写入的消息。问题是,当我更改消息并单击按
在我的分段控件中,有时标题比其段宽。我怎样才能让它截断? 假设第 1 段的标题是 Text overlaps,第 2 段的名称是 ok。 我希望它看起来如何: [Text ov...| ok
我想创建一个带有重叠单元格的 uitableview,如下图所示。问题是,即使我为单元格的内容 View 设置 clipsToBounds = NO,单元格假标题(例如,将与前一个单元格重叠的西类牙语
有了这个CSS .addProblemClass{ width:300px; height:300px; /*width:25%; height:40%;*/
我有跨窗口移动的图像(2 行),当我离开页面选项卡时,然后返回它,所有图像都相互堆叠。 JS代码(记入jfriend00) function startMoving(img) { va
这是我的一段代码。图像在 23 毫秒后正常可见,但永远不会像第二行所示那样返回隐藏状态。如果我将其从 17 毫秒更改为大于 23 毫秒的值,它就会起作用。反之亦然,如果我将第一行更改为 16 毫秒,它
我正在可汗学院为学校项目编写一款太空入侵者游戏,但我不知道如何在子弹和外星人之间进行碰撞,然后摆脱子弹所碰撞的外星人。这是非常基本的 JS,尽管我尝试过,但我不太明白如何将有关该主题的其他答案放入我的
当我尝试重新加载 tableView 的数据时出现奇怪的重叠,导致单元格的高度发生变化(使用 UITableViewAutomaticDimension),然后内容与上面的单元格重叠,无法弄清楚怎么做
我是一个新手,如果这是一个愚蠢的问题,请原谅我。我想有一个部分与标题分开,但发生了两种情况: (1) 当我把 在 下面,它们相互重叠,如下所示: Section overlapping header
我正在尝试创建两个 那是重叠的。唯一的问题是第二个 在第一个的前面它必须是相反的。我尝试设置第一个 的 z-index至 1但它仍然不起作用。 这是我的代码: #content{ backgrou
是否有重叠 2 个 div 的有效方法。 我有以下内容,但无法让它们重叠。 #top-border{width:100%; height:60px; background:url(image.jpg)
我是一名优秀的程序员,十分优秀!