Skip to content

Instantly share code, notes, and snippets.

@craiga
Created September 21, 2012 01:49
Show Gist options
  • Save craiga/3759346 to your computer and use it in GitHub Desktop.
Save craiga/3759346 to your computer and use it in GitHub Desktop.
strtobytes
<?php
/**
* Parse a description of a number of bytes to an actual number of bytes.
*
* @author Craig Anderson <[email protected]>
* @link https://gist.github.com/3759346
*/
function strtobytes($dataSize)
{
$multipliers = array(
"" => 1,
"b" => 1,
"byte" => 1,
"k" => 1000,
"kb" => 1000,
"kilobyte" => 1000,
"kib" => 1024,
"kibibyte" => 1024,
"m" => 1000 * 1000,
"mb" => 1000 * 1000,
"meg" => 1000 * 1000,
"megabyte" => 1000 * 1000,
"mib" => 1024 * 1024,
"mibibyte" => 1024 * 1024,
"g" => 1000 * 1000 * 1000,
"gb" => 1000 * 1000 * 1000,
"gig" => 1000 * 1000 * 1000,
"gigabyte" => 1000 * 1000 * 1000,
"gib" => 1024 * 1024 * 1024,
"gibibyte" => 1024 * 1024 * 1024,
"t" => 1000 * 1000 * 1000 * 1000,
"tb" => 1000 * 1000 * 1000 * 1000,
"terabyte" => 1000 * 1000 * 1000 * 1000,
"tib" => 1024 * 1024 * 1024 * 1024,
"tibibyte" => 1024 * 1024 * 1024 * 1024,
"p" => 1000 * 1000 * 1000 * 1000 * 1000,
"pb" => 1000 * 1000 * 1000 * 1000 * 1000,
"petabyte" => 1000 * 1000 * 1000 * 1000 * 1000,
"pib" => 1024 * 1024 * 1024 * 1024 * 1024,
"pibibyte" => 1024 * 1024 * 1024 * 1024 * 1024,
);
$bytes = NAN;
$dataSize = trim($dataSize);
if(strlen($dataSize) < 1)
{
// ignore empty string
}
else if(preg_match("/^(\\-?[\\d\\.\\,]+)?(.*)?$/", $dataSize, $matches))
{
$num = $matches[1];
$num = str_replace(",", "", $num); // remove thousands seperator (TODO: internationalise?)
$unit = trim(strtolower($matches[2]));
if(preg_match("/s$/", $unit) && $num == "")
{
// ignore plural units with no number
// i.e. "kilobyte" makes sense (1000), but "kilobytes" doesn't.
}
else
{
if($num == "")
{
$num = 1;
}
$unit = rtrim($unit, "s"); // depluralise
if(isset($multipliers[$unit]))
{
$bytes = round_out($num * $multipliers[$unit]);
}
}
}
return $bytes;
}
function round_out($num)
{
$result = 0;
if($num > 0)
{
$result = ceil($num);
}
else if($num < 0)
{
$result = floor($num);
}
return $result;
}
function num_decimals($num)
{
$numDecimals = strlen(strstr($num, ".")) - 1;
if($numDecimals < 0)
{
$numDecimals = 0;
}
return $numDecimals;
}
function test_strtobytes()
{
function assert_strtobytes($input, $expected)
{
$fail = true;
printf("strtobytes(\"%s\") = \"%s\"?\n", $input, $expected);
$actual = strtobytes($input);
if($actual == $expected || (is_nan($actual) && is_nan($expected)))
{
$fail = false;
}
else
{
printf("\nFAIL!\nstrtobytes(\"%s\") != \"%s\"\nstrtobytes(\"%s\") == \"%s\"\n", $input, $expected, $input, $actual);
die();
}
return $fail;
}
$dataMeasurements = array(
"b" => 1,
"byte" => 1,
"k" => 1000,
"kb" => 1000,
"kilobyte" => 1000,
"kib" => 1024,
"kibibyte" => 1024,
"m" => 1000 * 1000,
"mb" => 1000 * 1000,
"meg" => 1000 * 1000,
"megabyte" => 1000 * 1000,
"mib" => 1024 * 1024,
"mibibyte" => 1024 * 1024,
"g" => 1000 * 1000 * 1000,
"gb" => 1000 * 1000 * 1000,
"gig" => 1000 * 1000 * 1000,
"gigabyte" => 1000 * 1000 * 1000,
"gib" => 1024 * 1024 * 1024,
"gibibyte" => 1024 * 1024 * 1024,
"t" => 1000 * 1000 * 1000 * 1000,
"tb" => 1000 * 1000 * 1000 * 1000,
"terabyte" => 1000 * 1000 * 1000 * 1000,
"tib" => 1024 * 1024 * 1024 * 1024,
"tibibyte" => 1024 * 1024 * 1024 * 1024,
"p" => 1000 * 1000 * 1000 * 1000 * 1000,
"pb" => 1000 * 1000 * 1000 * 1000 * 1000,
"petabyte" => 1000 * 1000 * 1000 * 1000 * 1000,
"pib" => 1024 * 1024 * 1024 * 1024 * 1024,
"pibibyte" => 1024 * 1024 * 1024 * 1024 * 1024,
);
$nums = array(1, 0, 5, 12345, -1, -5, -12345, 0.1, 1.44, -0.1, ".1");
foreach($nums as $num)
{
assert_strtobytes($num, round_out($num));
}
foreach($dataMeasurements as $measurement => $numBytes)
{
assert_strtobytes(sprintf("%s", $measurement), $numBytes);
assert_strtobytes(sprintf("%s", strtoupper($measurement)), $numBytes);
assert_strtobytes(sprintf("%ss", $measurement), NAN);
assert_strtobytes(sprintf("%sS", strtoupper($measurement)), NAN);
foreach($nums as $num)
{
assert_strtobytes(sprintf("%s%s", $num, $measurement), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s%s", $num, strtoupper($measurement)), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s %s", $num, $measurement), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s %s", $num, strtoupper($measurement)), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s%ss", $num, $measurement), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s%sS", $num, strtoupper($measurement)), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s %ss", $num, $measurement), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s %sS", $num, strtoupper($measurement)), round_out($numBytes * $num));
assert_strtobytes(sprintf(" %s %s ", $num, $measurement), round_out($numBytes * $num));
assert_strtobytes(sprintf("%s %s", number_format($num, num_decimals($num)), $measurement), round_out($numBytes * $num));
}
}
assert_strtobytes("", NAN);
assert_strtobytes(" ", NAN);
assert_strtobytes("1 thing", NAN);
assert_strtobytes("1 x", NAN);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment