PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.15.0
Independent Analytics – WordPress Analytics Plugin v2.15.0
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 / UnsignedIntegerMath.php
independent-analytics / vendor / mlocati / ip-lib / src / Service Last commit date
BinaryMath.php 4 days ago NumberInChunks.php 4 days ago RangesFromBoundaryCalculator.php 4 days ago UnsignedIntegerMath.php 4 days ago
UnsignedIntegerMath.php
148 lines
1 <?php
2
3 namespace IAWPSCOPED\IPLib\Service;
4
5 /**
6 * Helper class to work with unsigned integers.
7 *
8 * @internal
9 */
10 class UnsignedIntegerMath
11 {
12 /**
13 * Convert a string containing a decimal, octal or hexadecimal number into its bytes.
14 *
15 * @param string $value
16 * @param int $numBytes the wanted number of bytes
17 * @param bool $onlyDecimal Only parse decimal numbers
18 *
19 * @return int[]|null
20 */
21 public function getBytes($value, $numBytes, $onlyDecimal = \false)
22 {
23 $m = null;
24 if ($onlyDecimal) {
25 if (\preg_match('/^0*(\\d+)$/', $value, $m)) {
26 return $this->getBytesFromDecimal($m[1], $numBytes);
27 }
28 } else {
29 if (\preg_match('/^0[Xx]0*([0-9A-Fa-f]+)$/', $value, $m)) {
30 return $this->getBytesFromHexadecimal($m[1], $numBytes);
31 }
32 if (\preg_match('/^0+([0-7]*)$/', $value, $m)) {
33 return $this->getBytesFromOctal($m[1], $numBytes);
34 }
35 if (\preg_match('/^[1-9][0-9]*$/', $value)) {
36 return $this->getBytesFromDecimal($value, $numBytes);
37 }
38 }
39 // Not a valid number
40 return null;
41 }
42 /**
43 * @return int
44 */
45 protected function getMaxSignedInt()
46 {
47 return \PHP_INT_MAX;
48 }
49 /**
50 * @param string $value never zero-length, never extra leading zeroes
51 * @param int $numBytes
52 *
53 * @return int[]|null
54 */
55 private function getBytesFromBits($value, $numBytes)
56 {
57 $valueLength = \strlen($value);
58 if ($valueLength > $numBytes << 3) {
59 // overflow
60 return null;
61 }
62 $remainderBits = $valueLength % 8;
63 if ($remainderBits !== 0) {
64 $value = \str_pad($value, $valueLength + 8 - $remainderBits, '0', \STR_PAD_LEFT);
65 }
66 $bytes = \array_map('bindec', \str_split($value, 8));
67 /** @var int[] $bytes */
68 return \array_pad($bytes, -$numBytes, 0);
69 }
70 /**
71 * @param string $value may be zero-length, never extra leading zeroes
72 * @param int $numBytes
73 *
74 * @return int[]|null
75 */
76 private function getBytesFromOctal($value, $numBytes)
77 {
78 if ($value === '') {
79 return \array_fill(0, $numBytes, 0);
80 }
81 $bits = \implode('', \array_map(function ($octalDigit) {
82 return \str_pad(\decbin((int) \octdec($octalDigit)), 3, '0', \STR_PAD_LEFT);
83 }, \str_split($value, 1)));
84 $bits = \ltrim($bits, '0');
85 return $bits === '' ? \array_fill(0, $numBytes, 0) : self::getBytesFromBits($bits, $numBytes);
86 }
87 /**
88 * @param string $value never zero-length, never extra leading zeroes
89 * @param int $numBytes
90 *
91 * @return int[]|null
92 */
93 private function getBytesFromDecimal($value, $numBytes)
94 {
95 $valueLength = \strlen($value);
96 $maxSignedIntLength = \strlen((string) $this->getMaxSignedInt());
97 if ($valueLength < $maxSignedIntLength) {
98 return $this->getBytesFromBits(\decbin((int) $value), $numBytes);
99 }
100 // Divide by two, so that we have 1 less bit
101 $carry = 0;
102 $halfValue = \ltrim(\implode('', \array_map(function ($digit) use(&$carry) {
103 $number = $carry + (int) $digit;
104 $carry = $number % 2 * 10;
105 return (string) $number >> 1;
106 }, \str_split($value, 1))), '0');
107 $halfValueBytes = $this->getBytesFromDecimal($halfValue, $numBytes);
108 if ($halfValueBytes === null) {
109 return null;
110 }
111 $carry = $carry === 0 ? 0 : 1;
112 $result = \array_fill(0, $numBytes, 0);
113 for ($index = $numBytes - 1; $index >= 0; $index--) {
114 $byte = $carry + ($halfValueBytes[$index] << 1);
115 if ($byte <= 0xff) {
116 $carry = 0;
117 } else {
118 $carry = ($byte & ~0xff) >> 8;
119 $byte -= 0x100;
120 }
121 $result[$index] = $byte;
122 }
123 if ($carry !== 0) {
124 // Overflow
125 return null;
126 }
127 return $result;
128 }
129 /**
130 * @param string $value never zero-length, never extra leading zeroes
131 * @param int $numBytes
132 *
133 * @return int[]|null
134 */
135 private function getBytesFromHexadecimal($value, $numBytes)
136 {
137 $valueLength = \strlen($value);
138 if ($valueLength > $numBytes << 1) {
139 // overflow
140 return null;
141 }
142 $value = \str_pad($value, $valueLength + $valueLength % 2, '0', \STR_PAD_LEFT);
143 $bytes = \array_map('hexdec', \str_split($value, 2));
144 /** @var int[] $bytes */
145 return \array_pad($bytes, -$numBytes, 0);
146 }
147 }
148