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 All 120 releases
independent-analytics / vendor / mlocati / ip-lib / src / Service / UnsignedIntegerMath.php
UnsignedIntegerMath.php
146 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
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 return \array_pad($bytes, -$numBytes, 0);
68 }
69 /**
70 * @param string $value may be zero-length, never extra leading zeroes
71 * @param int $numBytes
72 *
73 * @return int[]|null
74 */
75 private function getBytesFromOctal($value, $numBytes)
76 {
77 if ($value === '') {
78 return \array_fill(0, $numBytes, 0);
79 }
80 $bits = \implode('', \array_map(function ($octalDigit) {
81 return \str_pad(\decbin(\octdec($octalDigit)), 3, '0', \STR_PAD_LEFT);
82 }, \str_split($value, 1)));
83 $bits = \ltrim($bits, '0');
84 return $bits === '' ? \array_fill(0, $numBytes, 0) : static::getBytesFromBits($bits, $numBytes);
85 }
86 /**
87 * @param string $value never zero-length, never extra leading zeroes
88 * @param int $numBytes
89 *
90 * @return int[]|null
91 */
92 private function getBytesFromDecimal($value, $numBytes)
93 {
94 $valueLength = \strlen($value);
95 $maxSignedIntLength = \strlen((string) $this->getMaxSignedInt());
96 if ($valueLength < $maxSignedIntLength) {
97 return $this->getBytesFromBits(\decbin((int) $value), $numBytes);
98 }
99 // Divide by two, so that we have 1 less bit
100 $carry = 0;
101 $halfValue = \ltrim(\implode('', \array_map(function ($digit) use(&$carry) {
102 $number = $carry + (int) $digit;
103 $carry = $number % 2 * 10;
104 return (string) $number >> 1;
105 }, \str_split($value, 1))), '0');
106 $halfValueBytes = $this->getBytesFromDecimal($halfValue, $numBytes);
107 if ($halfValueBytes === null) {
108 return null;
109 }
110 $carry = $carry === 0 ? 0 : 1;
111 $result = \array_fill(0, $numBytes, 0);
112 for ($index = $numBytes - 1; $index >= 0; $index--) {
113 $byte = $carry + ($halfValueBytes[$index] << 1);
114 if ($byte <= 0xff) {
115 $carry = 0;
116 } else {
117 $carry = ($byte & ~0xff) >> 8;
118 $byte -= 0x100;
119 }
120 $result[$index] = $byte;
121 }
122 if ($carry !== 0) {
123 // Overflow
124 return null;
125 }
126 return $result;
127 }
128 /**
129 * @param string $value never zero-length, never extra leading zeroes
130 * @param int $numBytes
131 *
132 * @return int[]|null
133 */
134 private function getBytesFromHexadecimal($value, $numBytes)
135 {
136 $valueLength = \strlen($value);
137 if ($valueLength > $numBytes << 1) {
138 // overflow
139 return null;
140 }
141 $value = \str_pad($value, $valueLength + $valueLength % 2, '0', \STR_PAD_LEFT);
142 $bytes = \array_map('hexdec', \str_split($value, 2));
143 return \array_pad($bytes, -$numBytes, 0);
144 }
145 }
146