PHP 8.2: New ini_parse_quantity
function
PHP INI directives accept data sizes that can optionally contain a suffix to specify a unit multiplier, such as 5M
for 5 Megabytes, or 1G
for 1 Gigabyte. These suffixes are used widely in PHP INI files, but they are not international standardized suffixes.
ini_parse_quantity
is a new function added in to PHP in PHP 8.2. ini_parse_quantity
parses any data size recognized by PHP INI values (such as 56K
, 256M
, or 1G
) and returns the data size in bytes. This function can be useful when parsing existing or provided INI values in a PHP application.
The ini_parse_quantity
function does not recognize IEC suffixes for data sizes such as MB
, MiB
, or GB
, and is not suitable to convert standard data size values to bytes.
For example, 1K
is recognized in PHP INI values and ini_parse_quantity
function as one Kibibyte, which is equal to 1024
bytes. ini_parse_quantity
returns the parsed byte value following the exact approach PHP internally uses to parse INI values.
ini_parse_quantity
function synopsis
function ini_parse_quantity(string $shorthand): int {
}
ini_parse_quantity
function attempts to parse the given $shorthand
value by inspecting its last character suffix, and if it matches one of the following recognized suffixes, the returned value is multiplied by the unit specified to calculate the return value.
The following suffixes are recognized:
Suffix | Name | Multiplier |
---|---|---|
k / K |
Kibibytes | 1024 |
m / M |
Megabytes | 1048576 |
g / G |
Gigabytes | 1073741824 |
Note that this function emits warnings when it encounters a $shorthand
value containing unrecognized suffixes (e.g 53Q
), has no leading digits (R2D2
), when the parsed byte value is underflown or overflown (9999999999G
), or if the parser ignored unrecognized characters (12RG
). It does not throw any exceptions, and the caller may need to inspect the emitted warning message to make sure the value was parsed correctly.
Further, this function does not recognize decimal values (1.5G
).
ini_parse_quantity
function (and PHP's internal INI value parsing) is designed to try and work around incorrectly formatted strings as opposed to being defensive and throwing an exception. If the function cannot parse a value at all, it returns 0
.
Function Warning Messages
ini_parse_quantity
function emits several types of warnings if it encounters a value that does not comply with the exact format it expects.
- Values without leading digits return
0
Values without a valid digit at the beginning, such asABC
,T5
,S05e06
, are invalid. They result in a warning similar to the following, and the function returns0
:Invalid quantity "S06e08": no valid leading digits, interpreting as "0" for backwards compatibility
-
Values without recognized suffix return the first found integer value Unit sizes not recognized by the function are ignored, and the absolute integer value contained in the passed value is returned.
123R2D2
is parsed as"123"
1234T
is parsed as"123"
-1234T
is parsed as"-123"
Although an integer value is extracted, invalid values like this still result in a PHP warning:
Invalid quantity "123R2D2": unknown multiplier "2", interpreting as "123" for backwards compatibility
-
Values with unrecognized characters in the middle return the quantified value with a warning If the passed value contains characters that were removed, a warning is emitted, but the function returns the parsed and quantified value.
123FG
is parsed as"123G"
to132070244352
123$M
is parsed as"123M"
to44040192
-123MM
is parsed as"-123M"
to-128974848
Although an integer value is extracted, invalid values like this still result in a PHP warning:
Invalid quantity "123R2D2": unknown multiplier "2", interpreting as "123" for backwards compatibility
-
Values that overflow/underflow return overflown/underflown value If the calculated value is not between the minimum and maximum integer size the CPU can handle, a warning is emitted, and the function returns the overflown/underflown value.
9999999999G
is calculated to-7709325834783293440
-9999999999G
is calculated to7709325834783293440
The values above are overflown, but the function returns a value to be compatible with the INI parsing behavior. This condition is warned as well:
Invalid quantity "-9999999999G": value is out of range, using overflow result for backwards compatibility
User-land PHP Implementation
The following is a user-land PHP implementation of the PHP 8.2 ini_parse_quantity
function that should work on PHP 7.0 and later. It emits the same warnings as PHP 8.2 ini_parse_quantity
function.
function ini_parse_quantity(string $shorthand): int {
$original_shorthand = $shorthand;
$multiplier = 1;
$sign = '';
$return_value = 0;
$shorthand = trim($shorthand);
// Return 0 for empty strings.
if ($shorthand === '') {
return 0;
}
// Accept + and - as the sign.
if ($shorthand[0] === '-' || $shorthand[0] === '+') {
if ($shorthand[0] === '-') {
$multiplier = -1;
$sign = '-';
}
$shorthand = substr($shorthand, 1);
}
// If there is no suffix, return the integer value with the sign.
if (preg_match('/^\d+$/', $shorthand, $matches)) {
return $multiplier * $matches[0];
}
// Return 0 with a warning if there are no leading digits
if (preg_match('/^\d/', $shorthand) === 0) {
trigger_error(sprintf('Invalid quantity "%s": no valid leading digits, interpreting as "0" for backwards compatibility', $original_shorthand), E_USER_WARNING);
return $return_value;
}
// Removing whitespace characters.
$shorthand = preg_replace('/\s/', '', $shorthand);
$suffix = strtoupper(substr($shorthand, -1));
switch ($suffix) {
case 'K':
$multiplier *= 1024;
break;
case 'M':
$multiplier *= 1024 * 1024;
break;
case 'G':
$multiplier *= 1024 * 1024 * 1024;
break;
default:
preg_match('/\d+/', $shorthand, $matches);
trigger_error(sprintf('Invalid quantity "%s": unknown multiplier "%s", interpreting as "%d" for backwards compatibility', $original_shorthand, $suffix, $sign . $matches[0]), E_USER_WARNING );
return $matches[0] * $multiplier;
}
$stripped_shorthand = preg_replace('/^(\d+)(\D.*)([kKmMgG])$/', '$1$3', $shorthand, -1, $count);
if ($count > 0) {
trigger_error(sprintf('Invalid quantity "%s", interpreting as "%s" for backwards compatibility', $original_shorthand, $sign . $stripped_shorthand), E_USER_WARNING);
}
preg_match('/\d+/', $shorthand, $matches);
$multiplied = $matches[0] * $multiplier;
if (is_float($multiplied)) {
trigger_error(sprintf('Invalid quantity "%s": value is out of range, using overflow result for backwards compatibility', $original_shorthand), E_USER_WARNING);
}
return (int) ($matches[0] * $multiplier);
}
Backwards Compatibility Impact
ini_parse_quantity
is a new PHP function added in PHP 8.2. This function is added with some internal code refactoring to the PHP engine, which causes PHP to emit warnings when parsing a provided INI file.
However, the ini_parse_quantity
function can be trivially implemented in user-land PHP code in case an application or a library needs to make use of this function in an older PHP version.