Added byte formatting methods.

This commit is contained in:
flash 2023-07-05 23:07:54 +00:00
parent 8f908d7f68
commit 1cd1695429
4 changed files with 190 additions and 2 deletions

View file

@ -1 +1 @@
0.2307.50127
0.2307.52303

85
src/ByteFormat.php Normal file
View file

@ -0,0 +1,85 @@
<?php
// ByteFormat.php
// Created: 2023-07-05
// Updated: 2023-07-05
namespace Index;
final class ByteFormat {
/**
* Whether the default behaviour for the format function is decimal (power of 10) or not (power of 2).
*
* @var bool
*/
public const DECIMAL_DEFAULT = true;
private const SYMBOLS = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'];
private const DIV_DECIMAL = 1000;
private const DIV_BINARY = 1024;
/**
* Formats a raw amount of bytes as a human readable string.
*
* @param int $bytes Number of bytes.
* @param bool $decimal Whether format as a power of 10 (e.g. MB) or a power of 2 (e.g. MiB).
* @return string Formatted byte string.
*/
public static function format(int $bytes, bool $decimal = self::DECIMAL_DEFAULT): string {
// this whole thing will be fun if i ever decide to do localisation
if($bytes === 0)
return 'Zero Bytes';
$negative = $bytes < 0;
$bytes = abs($bytes);
$power = $decimal ? self::DIV_DECIMAL : self::DIV_BINARY;
$exp = floor(log($bytes) / log($power));
$number = $bytes / pow($power, $exp);
$symbol = self::SYMBOLS[$exp];
$string = '';
if($negative)
$string .= '-';
if($bytes < $power)
$string .= $number;
else if($number < 10)
$string .= sprintf('%.2f', $number);
else
$string .= sprintf('%.1f', $number);
$string .= ' ' . $symbol;
if($symbol === '') {
$string .= 'Byte';
if($number > 1)
$string .= 's';
} else {
if(!$decimal)
$string .= 'i';
$string .= 'B';
}
return $string;
}
/**
* Formats a raw amount of bytes as a human readable string in the power of 10 (e.g. MB).
*
* @param int $bytes Number of bytes.
* @return string Formatted byte string.
*/
public static function formatDecimal(int $bytes): string {
return self::format($bytes, true);
}
/**
* Formats a raw amount of bytes as a human readable string in the power of 2 (e.g. MiB).
*
* @param int $bytes Number of bytes.
* @return string Formatted byte string.
*/
public static function formatBinary(int $bytes): string {
return self::format($bytes, false);
}
}

View file

@ -42,7 +42,7 @@ final class XString {
/**
* Counts unique characters in a string.
*
* @param string String to count unique characters of.
* @param string $string String to count unique characters of.
* @return int Unique character count.
*/
public static function countUnique(string $string): int {

103
tests/ByteFormatTest.php Normal file
View file

@ -0,0 +1,103 @@
<?php
// ByteFormatTest.php
// Created: 2023-07-05
// Updated: 2023-07-05
declare(strict_types=1);
use PHPUnit\Framework\TestCase;
use Index\ByteFormat;
/**
* @covers ByteFormat
*/
final class ByteFormatTest extends TestCase {
public function testFormat(): void {
$this->assertEquals(ByteFormat::formatDecimal(0), 'Zero Bytes');
$this->assertEquals(ByteFormat::formatBinary(0), 'Zero Bytes');
$this->assertEquals(ByteFormat::formatDecimal(64), '64 Bytes');
$this->assertEquals(ByteFormat::formatBinary(64), '64 Bytes');
$this->assertEquals(ByteFormat::formatDecimal(-64), '-64 Bytes');
$this->assertEquals(ByteFormat::formatBinary(-64), '-64 Bytes');
$this->assertEquals(ByteFormat::formatDecimal(512), '512 Bytes');
$this->assertEquals(ByteFormat::formatBinary(512), '512 Bytes');
$this->assertEquals(ByteFormat::formatDecimal(-512), '-512 Bytes');
$this->assertEquals(ByteFormat::formatBinary(-512), '-512 Bytes');
$this->assertEquals(ByteFormat::formatDecimal(1000), '1.00 KB');
$this->assertEquals(ByteFormat::formatBinary(1000), '1000 Bytes');
$this->assertEquals(ByteFormat::formatDecimal(-1000), '-1.00 KB');
$this->assertEquals(ByteFormat::formatBinary(-1000), '-1000 Bytes');
$this->assertEquals(ByteFormat::formatDecimal(1024), '1.02 KB');
$this->assertEquals(ByteFormat::formatBinary(1024), '1.00 KiB');
$this->assertEquals(ByteFormat::formatDecimal(-1024), '-1.02 KB');
$this->assertEquals(ByteFormat::formatBinary(-1024), '-1.00 KiB');
$this->assertEquals(ByteFormat::formatDecimal(1000000), '1.00 MB');
$this->assertEquals(ByteFormat::formatBinary(1000000), '976.6 KiB');
$this->assertEquals(ByteFormat::formatDecimal(-1000000), '-1.00 MB');
$this->assertEquals(ByteFormat::formatBinary(-1000000), '-976.6 KiB');
$this->assertEquals(ByteFormat::formatDecimal(1048576), '1.05 MB');
$this->assertEquals(ByteFormat::formatBinary(1048576), '1.00 MiB');
$this->assertEquals(ByteFormat::formatDecimal(-1048576), '-1.05 MB');
$this->assertEquals(ByteFormat::formatBinary(-1048576), '-1.00 MiB');
$this->assertEquals(ByteFormat::formatDecimal(25252525), '25.3 MB');
$this->assertEquals(ByteFormat::formatBinary(25252525), '24.1 MiB');
$this->assertEquals(ByteFormat::formatDecimal(-25252525), '-25.3 MB');
$this->assertEquals(ByteFormat::formatBinary(-25252525), '-24.1 MiB');
$this->assertEquals(ByteFormat::formatDecimal(26476544), '26.5 MB');
$this->assertEquals(ByteFormat::formatBinary(26476544), '25.2 MiB');
$this->assertEquals(ByteFormat::formatDecimal(-26476544), '-26.5 MB');
$this->assertEquals(ByteFormat::formatBinary(-26476544), '-25.2 MiB');
$this->assertEquals(ByteFormat::formatDecimal(1000000000), '1.00 GB');
$this->assertEquals(ByteFormat::formatBinary(1000000000), '953.7 MiB');
$this->assertEquals(ByteFormat::formatDecimal(-1000000000), '-1.00 GB');
$this->assertEquals(ByteFormat::formatBinary(-1000000000), '-953.7 MiB');
$this->assertEquals(ByteFormat::formatDecimal(1073741824), '1.07 GB');
$this->assertEquals(ByteFormat::formatBinary(1073741824), '1.00 GiB');
$this->assertEquals(ByteFormat::formatDecimal(-1073741824), '-1.07 GB');
$this->assertEquals(ByteFormat::formatBinary(-1073741824), '-1.00 GiB');
$this->assertEquals(ByteFormat::formatDecimal(1000000000000), '1.00 TB');
$this->assertEquals(ByteFormat::formatBinary(1000000000000), '931.3 GiB');
$this->assertEquals(ByteFormat::formatDecimal(-1000000000000), '-1.00 TB');
$this->assertEquals(ByteFormat::formatBinary(-1000000000000), '-931.3 GiB');
$this->assertEquals(ByteFormat::formatDecimal(1099511627776), '1.10 TB');
$this->assertEquals(ByteFormat::formatBinary(1099511627776), '1.00 TiB');
$this->assertEquals(ByteFormat::formatDecimal(-1099511627776), '-1.10 TB');
$this->assertEquals(ByteFormat::formatBinary(-1099511627776), '-1.00 TiB');
$this->assertEquals(ByteFormat::formatDecimal(1000000000000000), '1.00 PB');
$this->assertEquals(ByteFormat::formatBinary(1000000000000000), '909.5 TiB');
$this->assertEquals(ByteFormat::formatDecimal(-1000000000000000), '-1.00 PB');
$this->assertEquals(ByteFormat::formatBinary(-1000000000000000), '-909.5 TiB');
$this->assertEquals(ByteFormat::formatDecimal(1125899906842624), '1.13 PB');
$this->assertEquals(ByteFormat::formatBinary(1125899906842624), '1.00 PiB');
$this->assertEquals(ByteFormat::formatDecimal(-1125899906842624), '-1.13 PB');
$this->assertEquals(ByteFormat::formatBinary(-1125899906842624), '-1.00 PiB');
}
}