Bytes   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 225
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
eloc 93
c 0
b 0
f 0
dl 0
loc 225
ccs 24
cts 24
cp 1
rs 10
wmc 8

3 Methods

Rating   Name   Duplication   Size   Complexity  
A base2() 0 3 1
A base10() 0 3 1
B format() 0 48 6
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
Protected member variable "notations" must contain a leading underscore
Loading history...
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
Coding Style introduced by
Protected member variable "base" must contain a leading underscore
Loading history...
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
Coding Style introduced by
Variable "useBase10" contains numbers but this is discouraged
Loading history...
165
        ?int $base = null,
166
        string $format = '%01.2f %s'
167
    ): string {
168
        // phpcs:enable
169
170 5
        $units = $useBase10
0 ignored issues
show
Coding Style introduced by
Variable "useBase10" contains numbers but this is discouraged
Loading history...
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