/// <summary> /// Converts any JavaScript value to a primitive number value. /// </summary> /// <param name="value"> The value to convert. </param> /// <returns> A primitive number value. </returns> public static double ToNumber(object value) { if (value == null || value == Undefined.Value) { return(double.NaN); } if (value == Null.Value) { return(+0); } // Get the type: Type valuesType = value.GetType(); if (valuesType == typeof(double)) { return((double)value); } if (valuesType == typeof(int)) { return((double)(int)value); } if (valuesType == typeof(uint)) { return((double)(uint)value); } if (valuesType == typeof(byte)) { return((double)(byte)value); } if (valuesType == typeof(sbyte)) { return((double)(sbyte)value); } if (valuesType == typeof(short)) { return((double)(short)value); } if (valuesType == typeof(ushort)) { return((double)(ushort)value); } if (valuesType == typeof(float)) { return((double)(float)value); } if (valuesType == typeof(bool)) { return((bool)value ? 1 : 0); } if (valuesType == typeof(string)) { return(NumberParser.CoerceToNumber((string)value)); } // If all else fails, use the string: double number = NumberParser.CoerceToNumber(value.ToString()); if (number == double.NaN) { throw new ArgumentException("Cannot convert object of type '" + valuesType + "' to a number.", "value"); } return(number); }
/// <summary> /// Converts a string to a number (used in type coercion). /// </summary> /// <returns> The result of parsing the string as a number. </returns> internal static double CoerceToNumber(string input) { var reader = new System.IO.StringReader(input); // Skip whitespace and line terminators. while (IsWhiteSpaceOrLineTerminator(reader.Peek())) { reader.Read(); } // Empty strings return 0. int firstChar = reader.Read(); if (firstChar == -1) { return(0.0); } // The number can start with a plus or minus sign. bool negative = false; switch (firstChar) { case '-': negative = true; firstChar = reader.Read(); break; case '+': firstChar = reader.Read(); break; } // Infinity or -Infinity are also valid. if (firstChar == 'I') { string restOfString1 = reader.ReadToEnd(); if (restOfString1.StartsWith("nfinity", StringComparison.Ordinal) == true) { // Check the end of the string for junk. for (int i = 7; i < restOfString1.Length; i++) { if (IsWhiteSpaceOrLineTerminator(restOfString1[i]) == false) { return(double.NaN); } } return(negative ? double.NegativeInfinity : double.PositiveInfinity); } } // Return NaN if the first digit is not a number or a period. if ((firstChar < '0' || firstChar > '9') && firstChar != '.') { return(double.NaN); } // Parse the number. NumberParser.ParseCoreStatus status; double result = NumberParser.ParseCore(reader, (char)firstChar, out status, false); // Handle various error cases. switch (status) { case ParseCoreStatus.NoDigits: case ParseCoreStatus.NoExponent: return(double.NaN); } // Check the end of the string for junk. string restOfString2 = reader.ReadToEnd(); for (int i = 0; i < restOfString2.Length; i++) { if (IsWhiteSpaceOrLineTerminator(restOfString2[i]) == false) { return(double.NaN); } } return(negative ? -result : result); }