// StringParseUtil.java /** * Copyright (C) 2008 10gen Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.mongodb.util; public final class StringParseUtil { /** Turns a string into a boolean value and returns a default value if unsuccessful. * @param s the string to convert * @param d the default value * @return equivalent boolean value */ public static boolean parseBoolean( String s , boolean d ){ if ( s == null ) return d; s = s.trim(); if ( s.length() == 0 ) return d; char c = s.charAt( 0 ); if ( c == 't' || c == 'T' || c == 'y' || c == 'Y' ) return true; if ( c == 'f' || c == 'F' || c == 'n' || c == 'N' ) return false; return d; } /** Turns a string into an int and returns a default value if unsuccessful. * @param s the string to convert * @param def the default value * @return the int value */ public static int parseInt( String s , int def ){ return parseInt( s , def , null , true ); } /** Turns a string into an int using a given radix. * @param s the string to convert * @param radix radix to use * @return the int value */ public static Number parseIntRadix( String s , int radix ){ if ( s == null ) return Double.NaN; s = s.trim(); if ( s.length() == 0 ) return Double.NaN; int firstDigit = -1; int i = 0; if ( s.charAt( 0 ) == '-' ) i = 1; // Find first non-digit. for ( ; i<s.length(); i++ ){ if ( Character.digit( s.charAt( i ) , radix ) == -1 ) break; } try { // Remember: all numbers in JS are 64-bit return Long.valueOf( s.substring( 0, i ) , radix ); } catch (Exception e) { return Double.NaN; } } /** Turns a string into an int and returns a default value if unsuccessful. * @param s the string to convert * @param def the default value * @param lastIdx sets lastIdx[0] to the index of the last digit * @param allowNegative if negative numbers are valid * @return the int value */ public static int parseInt( String s , int def , final int[] lastIdx , final boolean allowNegative ){ final boolean useLastIdx = lastIdx != null && lastIdx.length > 0; if ( useLastIdx ) lastIdx[0] = -1; if ( s == null ) return def; s = s.trim(); if ( s.length() == 0 ) return def; int firstDigit = -1; for ( int i=0; i<s.length(); i++ ){ if ( Character.isDigit( s.charAt( i ) ) ){ firstDigit = i; break; } } if ( firstDigit < 0 ) return def; int lastDigit = firstDigit + 1; while ( lastDigit < s.length() && Character.isDigit( s.charAt( lastDigit ) ) ) lastDigit++; if ( allowNegative && firstDigit > 0 && s.charAt( firstDigit - 1 ) == '-' ) firstDigit--; if ( useLastIdx ) lastIdx[0] = lastDigit; return Integer.parseInt( s.substring( firstDigit , lastDigit ) ); } /** Turns a string into a Number and returns a default value if unsuccessful. * @param s the string to convert * @param def the default value * @return the numeric value */ public static Number parseNumber( String s , Number def ){ if ( s == null ) return def; s = s.trim(); if ( s.length() == 0) return def; int firstDigit = -1; for ( int i=0; i<s.length(); i++ ){ if ( Character.isDigit( s.charAt( i ) ) ){ firstDigit = i; break; } } if ( firstDigit < 0 ) return def; int lastDigit = firstDigit + 1; while ( lastDigit < s.length() && Character.isDigit( s.charAt( lastDigit ) ) ) lastDigit++; boolean isDouble = false; if ( firstDigit > 0 && s.charAt( firstDigit - 1 ) == '.' ){ firstDigit--; isDouble = true; } if ( firstDigit > 0 && s.charAt( firstDigit - 1 ) == '-' ) firstDigit--; if ( lastDigit < s.length() && s.charAt( lastDigit ) == '.' ){ lastDigit++; while ( lastDigit < s.length() && Character.isDigit( s.charAt( lastDigit ) ) ) lastDigit++; isDouble = true; } if ( lastDigit < s.length() && s.charAt( lastDigit ) == 'E' ){ lastDigit++; while ( lastDigit < s.length() && Character.isDigit( s.charAt( lastDigit ) ) ) lastDigit++; isDouble = true; } final String actual = s.substring( firstDigit , lastDigit ); if ( isDouble || actual.length() > 17 ) return Double.valueOf( actual ); if ( actual.length() > 10 ) return Long.valueOf( actual ); return Integer.valueOf( actual ); } /** Use Java's "strict parsing" methods Integer.parseInt and Double.parseDouble to parse s "strictly". i.e. if it's neither a double or an integer, fail. * @param s the string to convert * @return the numeric value */ public static Number parseStrict( String s ){ if( s.length() == 0 ) return 0; if( s.charAt(0) == '+' ) s = s.substring( 1 ); if( s.matches( "(\\+|-)?Infinity" ) ) { if( s.startsWith( "-" ) ) { return Double.NEGATIVE_INFINITY; } else { return Double.POSITIVE_INFINITY; } } else if( s.indexOf('.') != -1 || s.equals( "-0" ) ) { return Double.valueOf(s); } // parse hex else if( s.toLowerCase().indexOf( "0x" ) > -1 ) { int coef = s.charAt( 0 ) == '-' ? -1 : 1; if( s.length() > 17 ) throw new RuntimeException( "Can't handle a number this big: "+s ); // if coef == -1: (coef * -.5 + 2.5) == 3 // e.g., -0xf00 (start substring at 3) // if coef == 1: (coef * -.5 + 2.5) == 2 // e.g., 0xf00 (start substring at 2) if( s.length() > 9 ) return coef * Long.valueOf( s.substring( (int)(coef * -.5 + 2.5) ) , 16 ); return coef * Integer.valueOf( s.substring( (int)(coef * -.5 + 2.5) ) , 16 ); } int e = s.toLowerCase().indexOf( 'e' ); // parse exp if( e > 0 ) { double num = Double.parseDouble( s.substring( 0, e ) ); int exp = Integer.parseInt( s.substring( e + 1 ) ); return num * Math.pow( 10 , exp ); } // parse with smallest possible precision if ( s.length() > 17 ) return Double.valueOf( s ); else if ( s.length() > 9 ) return Long.valueOf(s); return Integer.valueOf(s); } public static int parseIfInt( String s , int def ){ if ( s == null || s.length() == 0 ) return def; s = s.trim(); for ( int i=0; i<s.length(); i++ ) if ( ! Character.isDigit( s.charAt(i) ) ) return def; return Integer.parseInt( s ); } }