PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.5
Independent Analytics – WordPress Analytics Plugin v2.15.5
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 month ago NumberInChunks.php 1 month ago RangesFromBoundaryCalculator.php 1 month ago UnsignedIntegerMath.php 1 month ago
RangesFromBoundaryCalculator.php
161 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 = BinaryMath::getInstance();
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 * @return void
77 */
78 private function setNumBits($numBits)
79 {
80 $numBits = (int) $numBits;
81 $masks = array();
82 $unmasks = array();
83 for ($bit = 0; $bit < $numBits; $bit++) {
84 $masks[$bit] = \str_repeat('1', $numBits - $bit) . \str_repeat('0', $bit);
85 $unmasks[$bit] = $bit === 0 ? '0' : \str_repeat('1', $bit);
86 }
87 $this->numBits = $numBits;
88 $this->masks = $masks;
89 $this->unmasks = $unmasks;
90 }
91 /**
92 * Calculate the subnets.
93 *
94 * @param string $start the start address (represented in reduced bit form)
95 * @param string $end the end address (represented in reduced bit form)
96 * @param int $position the number of bits in the mask we are comparing at this cycle
97 * @param \IPLib\Range\Subnet[] $result found ranges will be added to this variable
98 *
99 * @return void
100 */
101 private function calculate($start, $end, $position, array &$result)
102 {
103 if ($start === $end) {
104 $result[] = $this->subnetFromBits($start, $this->numBits);
105 return;
106 }
107 $startMasked = '';
108 for ($index = $position - 1; $index >= 0; $index--) {
109 $startMasked = $this->math->andX($start, $this->masks[$index]);
110 $endMasked = $this->math->andX($end, $this->masks[$index]);
111 if ($startMasked !== $endMasked) {
112 $position = $index;
113 break;
114 }
115 }
116 if ($startMasked === $start && $this->math->andX($this->math->increment($end), $this->unmasks[$position]) === '0') {
117 $result[] = $this->subnetFromBits($start, $this->numBits - 1 - $position);
118 return;
119 }
120 $middleAddress = $this->math->orX($start, $this->unmasks[$position]);
121 $this->calculate($start, $middleAddress, $position, $result);
122 $this->calculate($this->math->increment($middleAddress), $end, $position, $result);
123 }
124 /**
125 * Create an address instance starting from its bits.
126 *
127 * @param string $bits the bits of the address (represented in reduced bit form)
128 *
129 * @return \IPLib\Address\AddressInterface
130 */
131 private function addressFromBits($bits)
132 {
133 $bits = \str_pad($bits, $this->numBits, '0', \STR_PAD_LEFT);
134 $bytes = array();
135 foreach (\explode("\n", \trim(\chunk_split($bits, 8, "\n"))) as $byteBits) {
136 $bytes[] = (int) \bindec($byteBits);
137 }
138 $result = Factory::addressFromBytes($bytes);
139 /** @var AddressInterface $result */
140 return $result;
141 }
142 /**
143 * Create an range instance starting from the bits if the address and the length of the network prefix.
144 *
145 * @param string $bits the bits of the address (represented in reduced bit form)
146 * @param int $networkPrefix the length of the network prefix
147 *
148 * @return \IPLib\Range\Subnet
149 */
150 private function subnetFromBits($bits, $networkPrefix)
151 {
152 $startAddress = $this->addressFromBits($bits);
153 $numOnes = $this->numBits - $networkPrefix;
154 if ($numOnes === 0) {
155 return new Subnet($startAddress, $startAddress, $networkPrefix);
156 }
157 $endAddress = $this->addressFromBits(\substr($bits, 0, -$numOnes) . \str_repeat('1', $numOnes));
158 return new Subnet($startAddress, $endAddress, $networkPrefix);
159 }
160 }
161