1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughespackage java.lang; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Used to parse a string and return either a single or double precision 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * floating point number. 23dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughes * @hide 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 25dc915c69ba2495dd2cf965d16058d0b13762142cElliott Hughesfinal class StringToReal { 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 271f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes private static final class StringExponentPair { 281f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes String s; 29750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes long e; 301f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes boolean negative; 311f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 32750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // Flags for two special non-error failure cases. 33750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes boolean infinity; 34750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes boolean zero; 35750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes 36750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes public float specialValue() { 37750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (infinity) { 38750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; 39750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 40750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return negative ? -0.0f : 0.0f; 411f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 421f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 431f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 441f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes /** 451f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * Takes a String and an integer exponent. The String should hold a positive 461f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * integer value (or zero). The exponent will be used to calculate the 471f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * floating point number by taking the positive integer the String 481f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * represents and multiplying by 10 raised to the power of the of the 49750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes * exponent. Returns the closest double value to the real number, or Double.longBitsToDouble(-1). 501f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes */ 511f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes private static native double parseDblImpl(String s, int e); 521f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 531f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes /** 541f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * Takes a String and an integer exponent. The String should hold a positive 551f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * integer value (or zero). The exponent will be used to calculate the 561f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * floating point number by taking the positive integer the String 571f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * represents and multiplying by 10 raised to the power of the of the 58750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes * exponent. Returns the closest float value to the real number, or Float.intBitsToFloat(-1). 591f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes */ 601f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes private static native float parseFltImpl(String s, int e); 611f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 621f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes private static NumberFormatException invalidReal(String s, boolean isDouble) { 631f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw new NumberFormatException("Invalid " + (isDouble ? "double" : "float") + ": \"" + s + "\""); 641f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 651f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 661f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes /** 67750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes * Returns a StringExponentPair containing a String with no leading or trailing white 681f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * space and trailing zeroes eliminated. The exponent of the 691f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * StringExponentPair will be used to calculate the floating point number by 701f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * taking the positive integer the String represents and multiplying by 10 711f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * raised to the power of the of the exponent. 721f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes */ 731f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes private static StringExponentPair initialParse(String s, int length, boolean isDouble) { 74750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes StringExponentPair result = new StringExponentPair(); 751f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (length == 0) { 761f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 771f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 78750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.negative = (s.charAt(0) == '-'); 79750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes 80750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // We ignore trailing double or float indicators; the method you called determines 81750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // what you'll get. 82750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes char c = s.charAt(length - 1); 831f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (c == 'D' || c == 'd' || c == 'F' || c == 'f') { 841f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes length--; 851f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (length == 0) { 861f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 871f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 881f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 891f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 90750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes int end = Math.max(s.indexOf('E'), s.indexOf('e')); 91750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (end != -1) { 92750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // Is there anything after the 'e'? 931f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (end + 1 == length) { 941f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 951f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 961f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 97750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // Do we have an optional explicit sign? 98750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes int exponentOffset = end + 1; 99750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes boolean negativeExponent = false; 100750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes char firstExponentChar = s.charAt(exponentOffset); 101750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (firstExponentChar == '+' || firstExponentChar == '-') { 102750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes negativeExponent = (firstExponentChar == '-'); 103750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes ++exponentOffset; 104750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 105750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes 106750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // Do we have a valid positive integer? 107750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes String exponentString = s.substring(exponentOffset, length); 108750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (exponentString.isEmpty()) { 109750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes throw invalidReal(s, isDouble); 110750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 111750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes for (int i = 0; i < exponentString.length(); ++i) { 112750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes char ch = exponentString.charAt(i); 113750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (ch < '0' || ch > '9') { 1141f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 1151f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1161f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 117750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes 118750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // Parse the integer exponent. 1191f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes try { 120750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.e = Integer.parseInt(exponentString); 121750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (negativeExponent) { 122750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.e = -result.e; 123750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 1241f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } catch (NumberFormatException ex) { 125750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // We already checked the string, so the exponent must have been out of range for an int. 126750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (negativeExponent) { 127750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.zero = true; 128750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } else { 129750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.infinity = true; 130750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 131750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return result; 1321f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1331f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } else { 1341f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes end = length; 1351f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1361f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (length == 0) { 1371f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 1381f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1391f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 140750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes int start = 0; 1411f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes c = s.charAt(start); 1421f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (c == '-') { 1431f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes ++start; 1441f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes --length; 145750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.negative = true; 1461f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } else if (c == '+') { 1471f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes ++start; 1481f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes --length; 1491f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1501f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (length == 0) { 1511f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 1521f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1531f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 154750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes int decimal = s.indexOf('.'); 1551f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (decimal > -1) { 156750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.e -= end - decimal - 1; 1571f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes s = s.substring(start, decimal) + s.substring(decimal + 1, end); 1581f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } else { 1591f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes s = s.substring(start, end); 1601f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1611f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 1621f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if ((length = s.length()) == 0) { 1631f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, isDouble); 1641f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1651f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 1661f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes end = length; 1671f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes while (end > 1 && s.charAt(end - 1) == '0') { 1681f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes --end; 1691f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1701f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 1711f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes start = 0; 1721f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes while (start < end - 1 && s.charAt(start) == '0') { 1731f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes start++; 1741f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 1751f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 1761f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (end != length || start != 0) { 177750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.e += length - end; 1781f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes s = s.substring(start, end); 1791f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 180a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson 181750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // This is a hack for https://issues.apache.org/jira/browse/HARMONY-329 182a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson // Trim the length of very small numbers, natives can only handle down 183a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson // to E-309 184a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson final int APPROX_MIN_MAGNITUDE = -359; 185a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson final int MAX_DIGITS = 52; 186a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson length = s.length(); 187750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (length > MAX_DIGITS && result.e < APPROX_MIN_MAGNITUDE) { 188750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes int d = Math.min(APPROX_MIN_MAGNITUDE - (int) result.e, length - 1); 189a389b4a499f40379b0b204d7ba1c2057663d95c0Jesse Wilson s = s.substring(0, length - d); 190750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.e += d; 191750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 192750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes 193750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // This is a hack for https://issues.apache.org/jira/browse/HARMONY-6641 194750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // The magic 1024 was determined experimentally; the more plausible -324 and +309 were 195750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes // not sufficient to pass both our tests and harmony's tests. 196750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (result.e < -1024) { 197750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.zero = true; 198750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return result; 199750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } else if (result.e > 1024) { 200750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.infinity = true; 201750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return result; 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 204750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes result.s = s; 205750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return result; 2061f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2071f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2088899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes // Parses "+Nan", "NaN", "-Nan", "+Infinity", "Infinity", and "-Infinity", case-insensitively. 2098899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes private static float parseName(String name, boolean isDouble) { 2108899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes // Explicit sign? 2111f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes boolean negative = false; 212866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes int i = 0; 2138899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes int length = name.length(); 2148899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes char firstChar = name.charAt(i); 215866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes if (firstChar == '-') { 216866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes negative = true; 217866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes ++i; 2188899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes --length; 219866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes } else if (firstChar == '+') { 220866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes ++i; 2218899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes --length; 2221f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2231f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2248899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes if (length == 8 && name.regionMatches(false, i, "Infinity", 0, 8)) { 2251f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes return negative ? Float.NEGATIVE_INFINITY : Float.POSITIVE_INFINITY; 2261f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2278899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes if (length == 3 && name.regionMatches(false, i, "NaN", 0, 3)) { 2281f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes return Float.NaN; 2291f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2308899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes throw invalidReal(name, isDouble); 2311f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2321f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2331f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes /** 2341f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * Returns the closest double value to the real number in the string. 2351f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * 2361f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * @param s 2371f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * the String that will be parsed to a floating point 2381f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * @return the double closest to the real number 2391f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * 2401f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * @exception NumberFormatException 2411f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * if the String doesn't represent a double 2421f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes */ 2431f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes public static double parseDouble(String s) { 2441f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes s = s.trim(); 2451f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes int length = s.length(); 2461f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2471f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (length == 0) { 2481f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, true); 2491f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2501f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2511f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes // See if this could be a named double 2521f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes char last = s.charAt(length - 1); 2538899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes if (last == 'y' || last == 'N') { 2548899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes return parseName(s, true); 2551f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 256f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 25778e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes // See if it could be a hexadecimal representation. 25878e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes // We don't use startsWith because there might be a leading sign. 25978e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes if (s.indexOf("0x") != -1 || s.indexOf("0X") != -1) { 260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return HexStringParser.parseDouble(s); 261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 262f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 2631f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes StringExponentPair info = initialParse(s, length, true); 264750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (info.infinity || info.zero) { 265750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return info.specialValue(); 266750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 267750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes double result = parseDblImpl(info.s, (int) info.e); 2681f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (Double.doubleToRawLongBits(result) == 0xffffffffffffffffL) { 2691f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, true); 2701f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 271750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return info.negative ? -result : result; 2721f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2731f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2741f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes /** 2751f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * Returns the closest float value to the real number in the string. 2761f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * 2771f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * @param s 2781f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * the String that will be parsed to a floating point 2791f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * @return the float closest to the real number 2801f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * 2811f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * @exception NumberFormatException 2821f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes * if the String doesn't represent a float 2831f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes */ 2841f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes public static float parseFloat(String s) { 2851f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes s = s.trim(); 2861f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes int length = s.length(); 2871f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2881f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (length == 0) { 2891f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, false); 2901f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 2911f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes 2921f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes // See if this could be a named float 2931f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes char last = s.charAt(length - 1); 2948899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes if (last == 'y' || last == 'N') { 2958899157a607a6bfd4ca4f361c77db8726885e47bElliott Hughes return parseName(s, false); 2961f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 297f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // See if it could be a hexadecimal representation 29978e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes // We don't use startsWith because there might be a leading sign. 30078e3320540c8bdcbefba5ae1222ee18f6679ab33Elliott Hughes if (s.indexOf("0x") != -1 || s.indexOf("0X") != -1) { 301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return HexStringParser.parseFloat(s); 302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 303f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes 3041f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes StringExponentPair info = initialParse(s, length, false); 305750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes if (info.infinity || info.zero) { 306750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return info.specialValue(); 307750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes } 308750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes float result = parseFltImpl(info.s, (int) info.e); 3091f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes if (Float.floatToRawIntBits(result) == 0xffffffff) { 3101f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes throw invalidReal(s, false); 3111f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 312750d24b13461035a89c9af8ec7555588da1cc3d0Elliott Hughes return info.negative ? -result : result; 3131f07ea29bc2d334c55c16227582a7795b8c117c1Elliott Hughes } 314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 315