/// <summary>
/// Converts a string to an integer (used by parseInt).
/// </summary>
/// <param name="radix"> The numeric base to use for parsing. Pass zero to use base 10
/// except when the input string starts with '0' in which case base 16 or base 8 are used
/// instead. </param>
/// <param name="allowOctal"> <c>true</c> if numbers with a leading zero should be parsed
/// as octal numbers. </param>
/// <returns> The result of parsing the string as a integer. </returns>
internal static double ParseInt(string input, int radix, bool allowOctal)
{
var reader = new System.IO.StringReader(input);
int digitCount = 0;
// Skip whitespace and line terminators.
while (IsWhiteSpaceOrLineTerminator(reader.Peek()))
{
reader.Read();
}
// Determine the sign.
double sign = 1;
if (reader.Peek() == '+')
{
reader.Read();
}
else if (reader.Peek() == '-')
{
sign = -1;
reader.Read();
}
// Hex prefix should be stripped if the radix is 0, undefined or 16.
bool stripPrefix = radix == 0 || radix == 16;
// Default radix is 10.
if (radix == 0)
{
radix = 10;
}
// Skip past the prefix, if there is one.
if (stripPrefix == true)
{
if (reader.Peek() == '0')
{
reader.Read();
digitCount = 1; // Note: required for parsing "0z11" correctly (when radix = 0).
int c = reader.Peek();
if (c == 'x' || c == 'X')
{
// Hex number.
reader.Read();
radix = 16;
}
if (c >= '0' && c <= '9' && allowOctal == true)
{
// Octal number.
radix = 8;
}
}
}
// Calculate the maximum number of digits before arbitrary precision arithmetic is
// required.
int maxDigits = (int)Math.Floor(53 / Math.Log(radix, 2));
// Read numeric digits 0-9, a-z or A-Z.
double result = 0;
var bigResult = BigInteger.Zero;
while (true)
{
int numericValue = -1;
int c = reader.Read();
if (c >= '0' && c <= '9')
{
numericValue = c - '0';
}
if (c >= 'a' && c <= 'z')
{
numericValue = c - 'a' + 10;
}
if (c >= 'A' && c <= 'Z')
{
numericValue = c - 'A' + 10;
}
if (numericValue == -1 || numericValue >= radix)
{
break;
}
if (digitCount == maxDigits)
{
bigResult = BigInteger.FromDouble(result);
}
result = result * radix + numericValue;
if (digitCount >= maxDigits)
{
bigResult = BigInteger.MultiplyAdd(bigResult, radix, numericValue);
}
digitCount++;
}
// If the input is empty, then return NaN.
if (digitCount == 0)
{
return(double.NaN);
}
// Numbers with lots of digits require the use of arbitrary precision arithmetic to
// determine the correct answer.
if (digitCount > maxDigits)
{
return(RefineEstimate(result, 0, bigResult) * sign);
}
return(result * sign);
}