1 | <?php |
||
2 | /** |
||
3 | * Copyright (c) 2010–2019 Ryan Parman <http://ryanparman.com>. |
||
4 | * Copyright (c) 2016–2019 Contributors. |
||
5 | * |
||
6 | * http://opensource.org/licenses/Apache2.0 |
||
7 | */ |
||
8 | |||
9 | declare(strict_types=1); |
||
10 | |||
11 | namespace SimplePie\UtilityPack\Util; |
||
12 | |||
13 | use RuntimeException; |
||
14 | |||
15 | class Bytes |
||
16 | { |
||
17 | // Multipliers |
||
18 | public const BYTE = 1; |
||
19 | |||
20 | public const BYTES = 1; |
||
21 | |||
22 | // Base 2 (e.g., 1024) |
||
23 | public const KIB = 1024; // 2 ** 10 |
||
24 | |||
25 | public const KIBIBYTE = 1024; // 2 ** 10 |
||
26 | |||
27 | public const KIBIBYTES = 1024; // 2 ** 10 |
||
28 | |||
29 | public const MIB = 1048576; // 2 ** 20 |
||
30 | |||
31 | public const MEBIBYTE = 1048576; // 2 ** 20 |
||
32 | |||
33 | public const MEBIBYTES = 1048576; // 2 ** 20 |
||
34 | |||
35 | public const GIB = 1073741824; // 2 ** 30 |
||
36 | |||
37 | public const GIBIBYTE = 1073741824; // 2 ** 30 |
||
38 | |||
39 | public const GIBIBYTES = 1073741824; // 2 ** 30 |
||
40 | |||
41 | public const TIB = 1099511627776; // 2 ** 40 |
||
42 | |||
43 | public const TEBIBYTE = 1099511627776; // 2 ** 40 |
||
44 | |||
45 | public const TEBIBYTES = 1099511627776; // 2 ** 40 |
||
46 | |||
47 | public const PIB = 1125899906842624; // 2 ** 50 |
||
48 | |||
49 | public const PEBIBYTE = 1125899906842624; // 2 ** 50 |
||
50 | |||
51 | public const PEBIBYTES = 1125899906842624; // 2 ** 50 |
||
52 | |||
53 | public const EIB = 1152921504606846976; // 2 ** 60 |
||
54 | |||
55 | public const EXBIBYTE = 1152921504606846976; // 2 ** 60 |
||
56 | |||
57 | public const EXBIBYTES = 1152921504606846976; // 2 ** 60 |
||
58 | |||
59 | // Base 10 (e.g., 1000) |
||
60 | public const KB = 1000; // 10 ** 3 |
||
61 | |||
62 | public const KILOBYTE = 1000; // 10 ** 3 |
||
63 | |||
64 | public const KILOBYTES = 1000; // 10 ** 3 |
||
65 | |||
66 | public const MB = 1000000; // 10 ** 6 |
||
67 | |||
68 | public const MEGABYTE = 1000000; // 10 ** 6 |
||
69 | |||
70 | public const MEGABYTES = 1000000; // 10 ** 6 |
||
71 | |||
72 | public const GB = 1000000000; // 10 ** 9 |
||
73 | |||
74 | public const GIGABYTE = 1000000000; // 10 ** 9 |
||
75 | |||
76 | public const GIGABYTES = 1000000000; // 10 ** 9 |
||
77 | |||
78 | public const TB = 1000000000000; // 10 ** 12 |
||
79 | |||
80 | public const TERABYTE = 1000000000000; // 10 ** 12 |
||
81 | |||
82 | public const TERABYTES = 1000000000000; // 10 ** 12 |
||
83 | |||
84 | public const PB = 1000000000000000; // 10 ** 15 |
||
85 | |||
86 | public const PETABYTE = 1000000000000000; // 10 ** 15 |
||
87 | |||
88 | public const PETABYTES = 1000000000000000; // 10 ** 15 |
||
89 | |||
90 | public const EB = 1000000000000000000; // 10 ** 18 |
||
91 | |||
92 | public const EXABYTE = 1000000000000000000; // 10 ** 18 |
||
93 | |||
94 | public const EXABYTES = 1000000000000000000; // 10 ** 18 |
||
95 | |||
96 | /** |
||
97 | * Notations for converted values. |
||
98 | * |
||
99 | * @var array |
||
100 | */ |
||
101 | protected static $notations = [ |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
102 | self::BYTES => 'b', |
||
103 | self::KILOBYTES => 'kB', |
||
104 | self::KIBIBYTES => 'kiB', |
||
105 | self::MEGABYTES => 'MB', |
||
106 | self::MEBIBYTES => 'MiB', |
||
107 | self::GIGABYTES => 'GB', |
||
108 | self::GIBIBYTES => 'GiB', |
||
109 | self::TERABYTES => 'TB', |
||
110 | self::TEBIBYTES => 'TiB', |
||
111 | self::PETABYTES => 'PB', |
||
112 | self::PEBIBYTES => 'PiB', |
||
113 | self::EXABYTES => 'EB', |
||
114 | self::EXBIBYTES => 'EiB', |
||
115 | ]; |
||
116 | |||
117 | /** |
||
118 | * Groupings of values determined by their base unit. |
||
119 | * |
||
120 | * @var array[] |
||
121 | */ |
||
122 | protected static $base = [ |
||
0 ignored issues
–
show
|
|||
123 | 2 => [ |
||
124 | self::BYTES, |
||
125 | self::KIBIBYTES, |
||
126 | self::MEBIBYTES, |
||
127 | self::GIBIBYTES, |
||
128 | self::TEBIBYTES, |
||
129 | self::PEBIBYTES, |
||
130 | self::EXBIBYTES, |
||
131 | ], |
||
132 | 10 => [ |
||
133 | self::BYTES, |
||
134 | self::KILOBYTES, |
||
135 | self::MEGABYTES, |
||
136 | self::GIGABYTES, |
||
137 | self::TERABYTES, |
||
138 | self::PETABYTES, |
||
139 | self::EXABYTES, |
||
140 | ], |
||
141 | ]; |
||
142 | |||
143 | /** |
||
144 | * Return human readable file sizes. |
||
145 | * |
||
146 | * @param int $bytes The number of bytes to format, as an integer. |
||
147 | * @param bool $useBase10 Whether or not to use `1000` for the base unit. A value of `true` means that `1000` |
||
148 | * will be used as the stepping unit. A value of `false` means that `1024` will be |
||
149 | * used as the stepping unit. |
||
150 | * @param int|null $base The base unit to lock to. By default, the base unit will increase as the values cross |
||
151 | * its threshold. If a value is passed here (should be one of the constants, and the |
||
152 | * constant must be _Base 2_ or _Base 10_ -- matching the `$useBase10` value). The |
||
153 | * default value is `null`, which means that the base unit is _unlocked_. |
||
154 | * @param string $format The final value is formatted using `sprintf()`. This is the format that should be |
||
155 | * used. The default value is `%01.2f %s`. |
||
156 | * |
||
157 | * @throws \ArithmeticError |
||
158 | * @throws RuntimeException |
||
159 | * |
||
160 | * phpcs:disable Generic.Functions.OpeningFunctionBraceBsdAllman.BraceOnSameLine |
||
161 | */ |
||
162 | 5 | public static function format( |
|
163 | int $bytes, |
||
164 | bool $useBase10 = true, |
||
0 ignored issues
–
show
|
|||
165 | ?int $base = null, |
||
166 | string $format = '%01.2f %s' |
||
167 | ): string { |
||
168 | // phpcs:enable |
||
169 | |||
170 | 5 | $units = $useBase10 |
|
0 ignored issues
–
show
|
|||
171 | 4 | ? self::$base[10] |
|
172 | 5 | : self::$base[2]; |
|
173 | |||
174 | // Do we have a base unit? |
||
175 | 5 | if ((bool) $base) { |
|
176 | // Make sure it's legit |
||
177 | 3 | if (!\array_search($base, $units, true)) { |
|
178 | 2 | throw new RuntimeException(\sprintf( |
|
179 | 'A base value of %s was used, which is not understood. Please use one of the class constants as ' |
||
180 | 2 | . 'a base value instead.', |
|
181 | 2 | (string) $base |
|
182 | )); |
||
183 | } |
||
184 | |||
185 | /** |
||
186 | * @psalm-suppress PossiblyNullArrayOffset |
||
187 | */ |
||
188 | 1 | return \sprintf( // @phan-suppress-current-line PhanPluginPrintfVariableFormatString |
|
189 | 1 | $format, |
|
190 | 1 | ($bytes / (int) $base), |
|
191 | 1 | (string) self::$notations[$base] |
|
192 | ); |
||
193 | } |
||
194 | |||
195 | // Otherwise, figure out the appropriate base unit |
||
196 | 3 | while (\count($units) > 0) { |
|
197 | 3 | $base = (int) \array_pop($units); |
|
198 | |||
199 | 3 | if ($bytes >= $base) { |
|
200 | // @phan-suppress-next-line PhanPluginPrintfVariableFormatString |
||
201 | 3 | return \sprintf( |
|
202 | 3 | $format, |
|
203 | 3 | ($bytes / $base), |
|
204 | 3 | (string) self::$notations[$base] |
|
205 | ); |
||
206 | } |
||
207 | } |
||
208 | |||
209 | throw new RuntimeException((string) $bytes); // @codeCoverageIgnore |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * Returns the Base 2 value of the stepping. |
||
214 | * |
||
215 | * * 0 = 0 |
||
216 | * * 1 = 1024 (kibi) |
||
217 | * * 2 = 1048576 (mebi) |
||
218 | * * 3 = 1073741824 (gibi) |
||
219 | * |
||
220 | * @param int $stepping The stepping to calculate the value for. |
||
221 | */ |
||
222 | 1 | public static function base2(int $stepping): int |
|
223 | { |
||
224 | 1 | return 2 ** (10 * $stepping); |
|
225 | } |
||
226 | |||
227 | /** |
||
228 | * Returns the Base 10 value of the stepping. |
||
229 | * |
||
230 | * * 0 = 0 |
||
231 | * * 1 = 1000 (kilo) |
||
232 | * * 2 = 1000000 (mega) |
||
233 | * * 3 = 1000000000 (giga) |
||
234 | * |
||
235 | * @param int $stepping The stepping to calculate the value for. |
||
236 | */ |
||
237 | 1 | public static function base10(int $stepping): int |
|
238 | { |
||
239 | 1 | return 10 ** (3 * $stepping); |
|
240 | } |
||
241 | } |
||
242 |