commons-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From scolebou...@apache.org
Subject cvs commit: jakarta-commons-sandbox/lang/src/java/org/apache/commons/lang Numbers.java
Date Mon, 08 Jul 2002 22:06:50 GMT
scolebourne    2002/07/08 15:06:50

  Modified:    lang/src/java/org/apache/commons/lang Numbers.java
  Log:
  Modified Numbers.isNumber to return true iff Numbers.createNumber can
  create a number.  
  from Rand McNeely
  
  Revision  Changes    Path
  1.6       +117 -37   jakarta-commons-sandbox/lang/src/java/org/apache/commons/lang/Numbers.java
  
  Index: Numbers.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/lang/src/java/org/apache/commons/lang/Numbers.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Numbers.java	5 Jul 2002 06:33:51 -0000	1.5
  +++ Numbers.java	8 Jul 2002 22:06:50 -0000	1.6
  @@ -138,9 +138,14 @@
        * <p>
        * If a type specifier is not found, it will check for a decimal point
        * and then try successively larger types from Integer to BigInteger 
  -     * and from Float to BigDecimal. If all else fails, the string will be 
  -     * interpreted as hex.
  +     * and from Float to BigDecimal.
        * </p>
  +     * <p>
  +     * If the string starts with "0x" or "-0x", it will be interpreted as a 
  +     * hexadecimal integer.  Values with leading 0's will not be interpreted 
  +     * as octal.
  +     * </p>
  +     * 
        * @param val String containing a number
        * @return Number created from the string
        * @throws NumberFormatException if the value cannot be converted
  @@ -149,7 +154,12 @@
           if (val == null) {
               return null;
           }
  -
  +        if (val.length() == 0) {
  +            throw new NumberFormatException("\"\" is not a valid number.");
  +        }
  +        if (val.startsWith("0x") || val.startsWith("-0x")) {
  +            return createInteger(val);
  +        }   
           char lastChar = val.charAt(val.length() - 1);
           String mant;
           String dec;
  @@ -163,29 +173,25 @@
                   if (expPos < decPos) {
                       throw new NumberFormatException(val + " is not a valid number.");
                   }
  -
                   dec = val.substring(decPos + 1, expPos);
  -                exp = val.substring(expPos + 1, val.length() - 1);
               } else {
                   dec = val.substring(decPos + 1);
  -                exp = null;
               }
               mant = val.substring(0, decPos);
           } else {
               if (expPos > -1) {
  -                if (expPos < val.length() - 1) {
  -                    exp = val.substring(expPos + 1, val.length() - 1);
  -                } else {
  -                    exp = null;
  -                }
                   mant = val.substring(0, expPos);
               } else {
                   mant = val;
  -                exp = null;
               }
               dec = null;
           }
           if (!Character.isDigit(lastChar)) {
  +            if (expPos > -1 && expPos < val.length() - 1) {
  +                exp = val.substring(expPos + 1, val.length() - 1);
  +            } else {
  +                exp = null;
  +            }
               //Requesting a specific type..
               String numeric = val.substring(0, val.length() - 1);
               boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
  @@ -233,13 +239,17 @@
                       }
                       //Fall through
                   default :
  -                    //We must have hex
  -                    return new Integer(Integer.parseInt(val, 16));
  +                    throw new NumberFormatException(val + " is not a valid number.");
   
               }
           } else {
               //User doesn't have a preference on the return type, so let's start
               //small and go from there...
  +            if (expPos > -1 && expPos < val.length() - 1) {
  +                exp = val.substring(expPos + 1, val.length());
  +            } else {
  +                exp = null;
  +            }
               if (dec == null && exp == null) {
                   //Must be an int,long,bigint
                   try {
  @@ -405,9 +415,14 @@
       }
   
       /**
  -     * Checks whether the String a valid Java number. [-][0-9][.][0-9].
  +     * <p>
  +     * Checks whether the String a valid Java number.
  +     * Valid numbers include hexadecimal marked with the "0x" qualifier,
  +     * scientific notation and numbers marked with a type qualifier (e.g. 123L).
  +     * </p>
  +     * <p>
        * Null and blank string will return false.
  -     * Doesn't allow scientific notation.
  +     * </p>
        * 
        * @param str  the string to check
        * @return true if the string is a correctly formatted number
  @@ -416,28 +431,93 @@
           if ((str == null) || (str.length() == 0)) {
               return false;
           }
  -        char[] chrs = str.toCharArray();
  -        int sz = chrs.length;
  -        boolean decimal = false;
  -        for (int i = 0; i < sz; i++) {
  -            // possibly faster as a continuous switch
  -            if ((chrs[i] >= '0') && (chrs[i] <= '9')) {
  -                continue;
  -            }
  -            if (i == 0) {
  -                if (chrs[i] == '-') {
  -                    continue;
  -                }
  -            }
  -            if (chrs[i] == '.') {
  -                if (!decimal) {
  -                    decimal = true;
  -                    continue;
  +        char[] chars = str.toCharArray();
  +        int sz = chars.length;
  +        boolean hasExp = false;
  +        boolean hasDecPoint = false;
  +        boolean allowSigns = false;
  +        boolean foundDigit = false;
  +        //Deal with any possible sign up front
  +        int start = (chars[0] == '-') ? 1 : 0;
  +        if (sz > start + 1) {
  +            if (chars[start] == '0' && chars[start + 1] == 'x') {
  +                int i = start + 2;
  +                if (i == sz) {
  +                    return false; // str == "0x"
                   }
  +                //Checking hex (it can't be anything else)
  +                for (; i < chars.length; i++) {
  +                    if ((chars[i] < '0' || chars[i] > '9')
  +                        && (chars[i] < 'a' || chars[i] > 'f')
  +                        && (chars[i] < 'A' || chars[i] > 'F')) {
  +                        return false;
  +                    }
  +                }
  +                return true;
               }
  -            return false;
           }
  -        return true;
  +        sz--; //Don't want to loop to the last char, check it afterwords
  +              //for type qualifiers
  +        int i = start;
  +        //Loop to the next to last char or to the last char if we need another digit to
  +        //make a valid number (e.g. chars[0..5] = "1234E")
  +        while (i < sz || (i < sz + 1 && allowSigns && !foundDigit))
{
  +            if (chars[i] >= '0' && chars[i] <= '9') {
  +                foundDigit = true;
  +                allowSigns = false;
  +
  +            } else if (chars[i] == '.') {
  +                if (hasDecPoint || hasExp) {
  +                    //Two decimal points or dec in exponent   
  +                    return false;
  +                }
  +                hasDecPoint = true;
  +            } else if (chars[i] == 'e' || chars[i] == 'E') {
  +                //We've already taken care of hex.
  +                if (hasExp) {
  +                    //Two E's
  +                    return false;
  +                }
  +                if (!foundDigit) {
  +                    return false;
  +                }
  +                hasExp = true;
  +                allowSigns = true;
  +            } else if (chars[i] == '+' || chars[i] == '-') {
  +                if (!allowSigns) {
  +                    return false;
  +                }
  +                allowSigns = false;
  +                foundDigit = false; //We need a digit after the E
  +            } else {
  +                return false;
  +            }
  +            i++;
  +        }
  +        if (i < chars.length) {
  +            if (chars[i] >= '0' && chars[i] <= '9') {
  +                //No type qualifier, OK
  +                return true;
  +            }
  +            if (chars[i] == 'e' || chars[i] == 'E') {
  +                //Can't have an E at the last byte
  +                return false;
  +            }
  +            if (!allowSigns
  +                && (chars[i] == 'd'
  +                    || chars[i] == 'D'
  +                    || chars[i] == 'f'
  +                    || chars[i] == 'F')) {
  +                return foundDigit;
  +            }
  +            if (chars[i] == 'l'
  +                || chars[i] == 'L') {
  +                //Not allowing L with an exponoent
  +                return foundDigit && !hasExp;
  +            }
  +        }
  +        //allowSigns is true iff the val ends in 'E'
  +        //Found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
  +        return !allowSigns && foundDigit;
       }
  -    
   }
  
  
  

--
To unsubscribe, e-mail:   <mailto:commons-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:commons-dev-help@jakarta.apache.org>


Mime
View raw message