PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.14.1
Independent Analytics – WordPress Analytics Plugin v2.14.1
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / vendor / mlocati / ip-lib / src / Service / RangesFromBoundaryCalculator.php
independent-analytics / vendor / mlocati / ip-lib / src / Service Last commit date
BinaryMath.php 1 year ago RangesFromBoundaryCalculator.php 1 year ago UnsignedIntegerMath.php 1 year ago
RangesFromBoundaryCalculator.php
154 lines
1 <?php
2
3 namespace IAWPSCOPED\IPLib\Service;
4
5 use IAWPSCOPED\IPLib\Address\AddressInterface;
6 use IAWPSCOPED\IPLib\Factory;
7 use IAWPSCOPED\IPLib\Range\Subnet;
8 /**
9 * Helper class to calculate the subnets describing all (and only all) the addresses between two boundaries.
10 *
11 * @internal
12 */
13 class RangesFromBoundaryCalculator
14 {
15 /**
16 * The BinaryMath instance to be used to perform bitwise operations.
17 *
18 * @var \IPLib\Service\BinaryMath
19 */
20 private $math;
21 /**
22 * The number of bits used to represent addresses.
23 *
24 * @var int
25 *
26 * @example 32 for IPv4, 128 for IPv6
27 */
28 private $numBits;
29 /**
30 * The bit masks for every bit index.
31 *
32 * @var string[]
33 */
34 private $masks;
35 /**
36 * The bit unmasks for every bit index.
37 *
38 * @var string[]
39 */
40 private $unmasks;
41 /**
42 * Initializes the instance.
43 *
44 * @param int $numBits the number of bits used to represent addresses (32 for IPv4, 128 for IPv6)
45 */
46 public function __construct($numBits)
47 {
48 $this->math = new BinaryMath();
49 $this->setNumBits($numBits);
50 }
51 /**
52 * Calculate the subnets describing all (and only all) the addresses between two boundaries.
53 *
54 * @param \IPLib\Address\AddressInterface $from
55 * @param \IPLib\Address\AddressInterface $to
56 *
57 * @return \IPLib\Range\Subnet[]|null return NULL if the two addresses have an invalid number of bits (that is, different from the one passed to the constructor of this class)
58 */
59 public function getRanges(AddressInterface $from, AddressInterface $to)
60 {
61 if ($from->getNumberOfBits() !== $this->numBits || $to->getNumberOfBits() !== $this->numBits) {
62 return null;
63 }
64 if ($from->getComparableString() > $to->getComparableString()) {
65 list($from, $to) = array($to, $from);
66 }
67 $result = array();
68 $this->calculate($this->math->reduce($from->getBits()), $this->math->reduce($to->getBits()), $this->numBits, $result);
69 return $result;
70 }
71 /**
72 * Set the number of bits used to represent addresses (32 for IPv4, 128 for IPv6).
73 *
74 * @param int $numBits
75 */
76 private function setNumBits($numBits)
77 {
78 $numBits = (int) $numBits;
79 $masks = array();
80 $unmasks = array();
81 for ($bit = 0; $bit < $numBits; $bit++) {
82 $masks[$bit] = \str_repeat('1', $numBits - $bit) . \str_repeat('0', $bit);
83 $unmasks[$bit] = $bit === 0 ? '0' : \str_repeat('1', $bit);
84 }
85 $this->numBits = $numBits;
86 $this->masks = $masks;
87 $this->unmasks = $unmasks;
88 }
89 /**
90 * Calculate the subnets.
91 *
92 * @param string $start the start address (represented in reduced bit form)
93 * @param string $end the end address (represented in reduced bit form)
94 * @param int $position the number of bits in the mask we are comparing at this cycle
95 * @param \IPLib\Range\Subnet[] $result found ranges will be added to this variable
96 */
97 private function calculate($start, $end, $position, array &$result)
98 {
99 if ($start === $end) {
100 $result[] = $this->subnetFromBits($start, $this->numBits);
101 return;
102 }
103 for ($index = $position - 1; $index >= 0; $index--) {
104 $startMasked = $this->math->andX($start, $this->masks[$index]);
105 $endMasked = $this->math->andX($end, $this->masks[$index]);
106 if ($startMasked !== $endMasked) {
107 $position = $index;
108 break;
109 }
110 }
111 if ($startMasked === $start && $this->math->andX($this->math->increment($end), $this->unmasks[$position]) === '0') {
112 $result[] = $this->subnetFromBits($start, $this->numBits - 1 - $position);
113 return;
114 }
115 $middleAddress = $this->math->orX($start, $this->unmasks[$position]);
116 $this->calculate($start, $middleAddress, $position, $result);
117 $this->calculate($this->math->increment($middleAddress), $end, $position, $result);
118 }
119 /**
120 * Create an address instance starting from its bits.
121 *
122 * @param string $bits the bits of the address (represented in reduced bit form)
123 *
124 * @return \IPLib\Address\AddressInterface
125 */
126 private function addressFromBits($bits)
127 {
128 $bits = \str_pad($bits, $this->numBits, '0', \STR_PAD_LEFT);
129 $bytes = array();
130 foreach (\explode("\n", \trim(\chunk_split($bits, 8, "\n"))) as $byteBits) {
131 $bytes[] = \bindec($byteBits);
132 }
133 return Factory::addressFromBytes($bytes);
134 }
135 /**
136 * Create an range instance starting from the bits if the address and the length of the network prefix.
137 *
138 * @param string $bits the bits of the address (represented in reduced bit form)
139 * @param int $networkPrefix the length of the network prefix
140 *
141 * @return \IPLib\Range\Subnet
142 */
143 private function subnetFromBits($bits, $networkPrefix)
144 {
145 $startAddress = $this->addressFromBits($bits);
146 $numOnes = $this->numBits - $networkPrefix;
147 if ($numOnes === 0) {
148 return new Subnet($startAddress, $startAddress, $networkPrefix);
149 }
150 $endAddress = $this->addressFromBits(\substr($bits, 0, -$numOnes) . \str_repeat('1', $numOnes));
151 return new Subnet($startAddress, $endAddress, $networkPrefix);
152 }
153 }
154