80 lines
2.1 KiB
PHP
80 lines
2.1 KiB
PHP
<?php
|
|
|
|
class Calc
|
|
{
|
|
public function merge(array $a, array $b): array
|
|
{
|
|
if ($b[0] > $a[1] + 1) {
|
|
$tmp = [$a, $b];
|
|
} elseif ($b[1] <= $a[1]) {
|
|
$tmp = [$a];
|
|
} else {
|
|
$tmp = [[$a[0], $b[1]]];
|
|
}
|
|
return array_filter($tmp);
|
|
}
|
|
|
|
public function substract(array $a, array $b): array
|
|
{
|
|
if ($b[0] > $a[1] || $b[1] < $a[0]) {
|
|
return [$a];
|
|
} elseif ($b[0] <= $a[0] && $b[1] >= $a[1]) {
|
|
return [];
|
|
} elseif ($b[0] > $a[0] && $b[1] < $a[1]) {
|
|
return [[$a[0], $b[0] - 1], [$b[1] + 1, $a[1]]];
|
|
} elseif ($b[0] <= $a[0]) {
|
|
return [$b[1] + 1, $a[1]];
|
|
} else {
|
|
return [$a[0], $b[1] - 1];
|
|
}
|
|
}
|
|
|
|
public function alignment(array $arr): array
|
|
{
|
|
usort($arr, fn ($a, $b) => $a[0] <=> $b[0]);
|
|
$tmp = [[]];
|
|
foreach ($arr as $k => $v) {
|
|
$t = array_pop($tmp);
|
|
$tmp = array_merge($tmp, $this->merge($t, $v));
|
|
}
|
|
return $tmp;
|
|
}
|
|
|
|
public function prepare(array $include, array $exclude): array
|
|
{
|
|
$include = $this->alignment($include);
|
|
if (!empty($exclude)) {
|
|
$tmp = [];
|
|
$exclude = $this->alignment($exclude);
|
|
foreach ($exclude as $k => $v) {
|
|
foreach ($include as $i => $j) {
|
|
$tmp = array_merge($tmp, $this->substract($j, $v));
|
|
}
|
|
$d = array_filter($tmp);
|
|
}
|
|
return $tmp;
|
|
}
|
|
return $include;
|
|
}
|
|
|
|
public function toCIDR(int $a, int $b)
|
|
{
|
|
$diff = $b - $a + 1;
|
|
if ($diff > 1) {
|
|
for ($i = 0; $i <= 32; $i++) {
|
|
if ($diff / (1 << $i) < 1) {
|
|
break;
|
|
}
|
|
}
|
|
$tmp[] = long2ip($a) . "/" . (32 - $i + 1);
|
|
$new = $a + (1 << ($i - 1));
|
|
if ($new <= $b) {
|
|
$tmp = array_merge($tmp, $this->toCIDR($new, $b));
|
|
}
|
|
} else {
|
|
$tmp[] = long2ip($a) . "/32";
|
|
}
|
|
return $tmp;
|
|
}
|
|
}
|