/// <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') { var restOfString1 = reader.ReadToEnd(); if (restOfString1 == null) { throw new InvalidOperationException("Reader returned null."); } if (restOfString1.StartsWith("nfinity", StringComparison.Ordinal)) { // 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, true, false); // Handle various error cases. switch (status) { case ParseCoreStatus.NoDigits: case ParseCoreStatus.NoExponent: return(double.NaN); } // Check the end of the string for junk. var nfinityString = reader.ReadToEnd(); if (nfinityString == null) { throw new InvalidOperationException("Reader returned null."); } if (nfinityString.Any(t => IsWhiteSpaceOrLineTerminator(t) == false)) { return(double.NaN); } return(negative ? -result : result); }
/// <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 is double) { return((double)value); } if (value is SByte) { return((SByte)value); } if (value is Int16) { return((Int16)value); } if (value is Int32) { return((Int32)value); } if (value is Int64) { return((Int64)value); } if (value is Byte) { return((Byte)value); } if (value is UInt16) { return((UInt16)value); } if (value is UInt32) { return((UInt32)value); } if (value is UInt64) { return((UInt64)value); } if (value == null || value == Undefined.Value) { return(double.NaN); } if (value == Null.Value) { return(+0); } if (value is bool) { return((bool)value ? 1 : 0); } if (value is string) { return(NumberParser.CoerceToNumber((string)value)); } if (value is ConcatenatedString) { return(NumberParser.CoerceToNumber(value.ToString())); } if (value is ObjectInstance) { return(ToNumber(ToPrimitive(value, PrimitiveTypeHint.Number))); } throw new ArgumentException(string.Format("Cannot convert object of type '{0}' to a number.", value.GetType()), "value"); }