/**
* Parses number in lenient mode.
*
* Lenient parsing ignores everything that can be ignored, and tries to
* extract number from the string, even if it's not well formed.
*
* Implementation is simple but should work more often than strict parsing.
*
* Algorithm:
* 1. Find first digit
* 2. Find last digit
* 3. Find decimal separator between first and last digit (if any)
* 4. Remove non-digits from integer part
* 5. Remove non-digits from decimal part (optional)
* 6. Try to match negative prefix before first digit
* 7. Try to match negative suffix after last digit
*
* @param string $numberToParse Number to be parsed
* @param array $parsedFormat Parsed format (from NumbersReader)
* @param array $localizedSymbols An array with symbols to use
* @return mixed Parsed float number or FALSE on failure
*/
protected function doParsingInLenientMode($numberToParse, array $parsedFormat, array $localizedSymbols)
{
$numberIsNegative = false;
$positionOfFirstDigit = null;
$positionOfLastDigit = null;
$charactersOfNumberString = str_split($numberToParse);
foreach ($charactersOfNumberString as $position => $character) {
if (ord($character) >= 48 && ord($character) <= 57) {
$positionOfFirstDigit = $position;
break;
}
}
if ($positionOfFirstDigit === null) {
return false;
}
krsort($charactersOfNumberString);
foreach ($charactersOfNumberString as $position => $character) {
if (ord($character) >= 48 && ord($character) <= 57) {
$positionOfLastDigit = $position;
break;
}
}
$positionOfDecimalSeparator = strrpos($numberToParse, $localizedSymbols['decimal'], $positionOfFirstDigit);
if ($positionOfDecimalSeparator === false) {
$integerPart = substr($numberToParse, $positionOfFirstDigit, $positionOfLastDigit - $positionOfFirstDigit + 1);
$decimalPart = false;
} else {
$integerPart = substr($numberToParse, $positionOfFirstDigit, $positionOfDecimalSeparator - $positionOfFirstDigit);
$decimalPart = substr($numberToParse, $positionOfDecimalSeparator + 1, $positionOfLastDigit - $positionOfDecimalSeparator);
}
$parsedNumber = (int) preg_replace(self::PATTERN_MATCH_NOT_DIGITS, '', $integerPart);
if ($decimalPart !== false) {
$decimalPart = (int) preg_replace(self::PATTERN_MATCH_NOT_DIGITS, '', $decimalPart);
$parsedNumber = (double) ($parsedNumber . '.' . $decimalPart);
}
$partBeforeNumber = substr($numberToParse, 0, $positionOfFirstDigit);
$partAfterNumber = substr($numberToParse, -(strlen($numberToParse) - $positionOfLastDigit - 1));
if (!empty($parsedFormat['negativePrefix']) && !empty($parsedFormat['negativeSuffix'])) {
if (Utility::stringEndsWith($partBeforeNumber, $parsedFormat['negativePrefix']) && Utility::stringBeginsWith($partAfterNumber, $parsedFormat['negativeSuffix'])) {
$numberIsNegative = true;
}
} elseif (!empty($parsedFormat['negativePrefix']) && Utility::stringEndsWith($partBeforeNumber, $parsedFormat['negativePrefix'])) {
$numberIsNegative = true;
} elseif (!empty($parsedFormat['negativeSuffix']) && Utility::stringBeginsWith($partAfterNumber, $parsedFormat['negativeSuffix'])) {
$numberIsNegative = true;
}
$parsedNumber /= $parsedFormat['multiplier'];
if ($numberIsNegative) {
$parsedNumber = 0 - $parsedNumber;
}
return $parsedNumber;
}