jpayne@68: package shared; jpayne@68: jpayne@68: import structures.ByteBuilder; jpayne@68: import structures.LongList; jpayne@68: jpayne@68: public class Parse { jpayne@68: jpayne@68: jpayne@68: public static int parseIntKMG(String b){ jpayne@68: long x=parseKMG(b); jpayne@68: assert(x<=Integer.MAX_VALUE && x>Integer.MIN_VALUE) : "Value "+x+" is out of range for integers: "+b; jpayne@68: return (int)x; jpayne@68: } jpayne@68: jpayne@68: public static long parseKMG(String b){ jpayne@68: if(b==null){return 0;} jpayne@68: assert(b.length()>0); jpayne@68: final char c=Tools.toLowerCase(b.charAt(b.length()-1)); jpayne@68: final boolean dot=b.indexOf('.')>=0; jpayne@68: if(!dot && !Tools.isLetter(c)){return Long.parseLong(b);} jpayne@68: // if(!Tools.isLetter(c) && !dot){return Long.parseLong(b);} jpayne@68: jpayne@68: if(b.equalsIgnoreCase("big") || b.equalsIgnoreCase("inf") || b.equalsIgnoreCase("infinity") || b.equalsIgnoreCase("max") || b.equalsIgnoreCase("huge")){ jpayne@68: return Long.MAX_VALUE; jpayne@68: } jpayne@68: jpayne@68: long mult=1; jpayne@68: if(Tools.isLetter(c)){ jpayne@68: if(c=='k'){mult=1000;} jpayne@68: else if(c=='m'){mult=1000000;} jpayne@68: else if(c=='g' || c=='b'){mult=1000000000;} jpayne@68: else if(c=='t'){mult=1000000000000L;} jpayne@68: else if(c=='p' || c=='q'){mult=1000000000000000L;} jpayne@68: else if(c=='e'){mult=1000000000000000000L;} jpayne@68: // else if(c=='z'){mult=1000000000000000000000L;}//Out of range jpayne@68: else if(c=='c' || c=='h'){mult=100;} jpayne@68: else if(c=='d'){mult=10;} jpayne@68: else{throw new RuntimeException(b);} jpayne@68: b=b.substring(0, b.length()-1); jpayne@68: } jpayne@68: jpayne@68: //Calculate product, check for overflow, and return jpayne@68: if(!dot){ jpayne@68: long m=Long.parseLong(b); jpayne@68: long p=m*mult; jpayne@68: assert(p>=m) : p+", "+m+", "+b; jpayne@68: return p; jpayne@68: }else{ jpayne@68: double m=Double.parseDouble(b); jpayne@68: long p=(long)(m*mult); jpayne@68: assert(p>=m) : p+", "+m+", "+b; jpayne@68: return p; jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: public static long parseKMGBinary(String b){ jpayne@68: if(b==null){return 0;} jpayne@68: char c=Tools.toLowerCase(b.charAt(b.length()-1)); jpayne@68: boolean dot=b.indexOf('.')>=0; jpayne@68: if(!Tools.isLetter(c) && !dot){return Long.parseLong(b);} jpayne@68: jpayne@68: long mult=1; jpayne@68: if(Tools.isLetter(c)){ jpayne@68: if(c=='k'){mult=1024;} jpayne@68: else if(c=='m'){mult=1024*1024;} jpayne@68: else if(c=='g' || c=='b'){mult=1024*1024*1024;} jpayne@68: else if(c=='t'){mult=1024L*1024L*1024L*1024L;} jpayne@68: else{throw new RuntimeException(b);} jpayne@68: b=b.substring(0, b.length()-1); jpayne@68: } jpayne@68: jpayne@68: if(!dot){return Long.parseLong(b)*mult;} jpayne@68: jpayne@68: return (long)(Double.parseDouble(b)*mult); jpayne@68: } jpayne@68: jpayne@68: public static boolean isNumber(String s){ jpayne@68: if(s==null || s.length()==0){return false;} jpayne@68: char c=s.charAt(0); jpayne@68: return Tools.isDigit(c) || c=='.' || c=='-'; jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * Parse this argument. More liberal than Boolean.parseBoolean. jpayne@68: * Null, t, true, or 1 all yield true. jpayne@68: * Everything else, including the String "null", is false. jpayne@68: * @param s Argument to parse jpayne@68: * @return boolean form jpayne@68: */ jpayne@68: public static boolean parseBoolean(String s){ jpayne@68: if(s==null || s.length()<1){return true;} jpayne@68: if(s.length()==1){ jpayne@68: char c=Tools.toLowerCase(s.charAt(0)); jpayne@68: return c=='t' || c=='1'; jpayne@68: } jpayne@68: if(s.equalsIgnoreCase("null") || s.equalsIgnoreCase("none")){return false;} jpayne@68: return Boolean.parseBoolean(s); jpayne@68: } jpayne@68: jpayne@68: public static boolean parseYesNo(String s){ jpayne@68: if(s==null || s.length()<1){return true;} jpayne@68: if(s.length()==1){ jpayne@68: char c=Tools.toLowerCase(s.charAt(0)); jpayne@68: if(c=='y'){return true;} jpayne@68: if(c=='n'){return false;} jpayne@68: throw new RuntimeException(s); jpayne@68: } jpayne@68: jpayne@68: if(s.equalsIgnoreCase("yes")){return true;} jpayne@68: if(s.equalsIgnoreCase("no")){return false;} jpayne@68: if(s.equalsIgnoreCase("unknown")){return false;} //Special case for IMG database jpayne@68: jpayne@68: throw new RuntimeException(s); jpayne@68: } jpayne@68: jpayne@68: public static int[] parseIntArray(String s, String regex){ jpayne@68: if(s==null){return null;} jpayne@68: String[] split=s.split(regex); jpayne@68: int[] array=new int[split.length]; jpayne@68: for(int i=0; i1 && s.charAt(1)=='0'){ jpayne@68: final char c=s.charAt(1); jpayne@68: if(c=='x' || c=='X'){radix=16;} jpayne@68: else if(c=='b' || c=='B'){radix=2;} jpayne@68: else if(c=='o' || c=='O'){radix=8;} jpayne@68: } jpayne@68: return Integer.parseInt(s, radix); jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param array Text jpayne@68: * @param a Index of first digit jpayne@68: * @param b Index after last digit (e.g., array.length) jpayne@68: * @return Parsed number jpayne@68: */ jpayne@68: public static float parseFloat(byte[] array, int a, int b){ jpayne@68: return (float)parseDouble(array, a, b); jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param array Text jpayne@68: * @param a Index of first digit jpayne@68: * @param b Index after last digit (e.g., array.length) jpayne@68: * @return Parsed number jpayne@68: */ jpayne@68: public static double parseDoubleSlow(byte[] array, int a, int b){ jpayne@68: String s=new String(array, a, b-a); jpayne@68: return Double.parseDouble(s); jpayne@68: } jpayne@68: jpayne@68: public static double parseDouble(final byte[] array, final int start){ jpayne@68: return parseDouble(array, start, array.length); jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param array Text jpayne@68: * @param a0 Index of first digit jpayne@68: * @param b Index after last digit (e.g., array.length) jpayne@68: * @return Parsed number jpayne@68: */ jpayne@68: public static double parseDouble(final byte[] array, final int a0, final int b){ jpayne@68: if(Tools.FORCE_JAVA_PARSE_DOUBLE){ jpayne@68: return Double.parseDouble(new String(array, a0, b-a0)); jpayne@68: } jpayne@68: int a=a0; jpayne@68: assert(b>a); jpayne@68: long upper=0; jpayne@68: final byte z='0'; jpayne@68: long mult=1; jpayne@68: if(array[a]=='-'){mult=-1; a++;} jpayne@68: jpayne@68: for(; a=0) : x+" = "+(char)c+"\narray="+new String(array)+", start="+a+", stop="+b; jpayne@68: upper=(upper*10)+x; jpayne@68: } jpayne@68: jpayne@68: long lower=0; jpayne@68: int places=0; jpayne@68: for(a++; a=0) : x+" = "+(char)c+"\narray="+new String(array)+", start="+a+", stop="+b+ jpayne@68: "\nThis function does not support exponents; if the input has an exponent, add the flag 'forceJavaParseDouble'."; jpayne@68: lower=(lower*10)+x; jpayne@68: places++; jpayne@68: } jpayne@68: jpayne@68: double d=mult*(upper+lower*ByteBuilder.decimalInvMult[places]); jpayne@68: // assert(d==parseDoubleSlow(array, a0, b)) : d+", "+parseDoubleSlow(array, a0, b); jpayne@68: return d; jpayne@68: } jpayne@68: jpayne@68: public static int parseInt(byte[] array, int start){ jpayne@68: return parseInt(array, start, array.length); jpayne@68: } jpayne@68: jpayne@68: // /** jpayne@68: // * @param array Text jpayne@68: // * @param a Index of first digit jpayne@68: // * @param b Index after last digit (e.g., array.length) jpayne@68: // * @return Parsed number jpayne@68: // */ jpayne@68: // public static int parseInt(byte[] array, int a, int b){ jpayne@68: // assert(b>a); jpayne@68: // int r=0; jpayne@68: // final byte z='0'; jpayne@68: // int mult=1; jpayne@68: // if(array[a]=='-'){mult=-1; a++;} jpayne@68: // for(; a=0) : x+" = "+(char)array[a]+"\narray="+new String(array)+", start="+a+", stop="+b; jpayne@68: // r=(r*10)+x; jpayne@68: // } jpayne@68: // return r*mult; jpayne@68: // } jpayne@68: jpayne@68: /** jpayne@68: * Returns the int representation of a number represented in ASCII text, from position a to b. jpayne@68: * This function is much faster than creating a substring and calling Integer.parseInt() jpayne@68: * Throws Assertions rather than Exceptions for invalid input. jpayne@68: * This function does NOT detect overflows, e.g., values over 2^31-1 (Integer.MAX_VALUE). jpayne@68: * This function has no side-effects. jpayne@68: * @param array byte array containing the text to parse. jpayne@68: * @param a Index of the first digit of the number. jpayne@68: * @param b Index after the last digit (e.g., array.length). jpayne@68: * @return int representation of the parsed number. jpayne@68: * @throws Assertions rather than Exceptions for invalid input. jpayne@68: * jpayne@68: * @TODO Correctly represent Integer.MIN_VALUE jpayne@68: * @TODO Detect overflow. jpayne@68: */ jpayne@68: public static int parseInt(byte[] array, int a, int b){ jpayne@68: assert(b>a) : "The start position of the text to parse must come before the stop position: "+ jpayne@68: a+","+b+","+new String(array); jpayne@68: int r=0; //Initialize the return value to 0. jpayne@68: jpayne@68: //z holds the ASCII code for 0, which is subtracted from other ASCII codes jpayne@68: //to yield the int value of a character. For example, '7'-'0'=7, jpayne@68: //because ASCII '7'=55, while ASCII '0'=48, and 55-48=7. jpayne@68: final byte z='0'; jpayne@68: jpayne@68: //mult is 1 for positive numbers, or -1 for negative numbers. jpayne@68: //It will be multiplied by the unsigned result to yield the final signed result. jpayne@68: int mult=1; jpayne@68: jpayne@68: //If the term starts with a minus sign, set the multiplier to -1 and increment the position. jpayne@68: if(array[a]=='-'){mult=-1; a++;} jpayne@68: jpayne@68: //Iterate through every position, incrementing a, up to b (exclusive). jpayne@68: for(; a=0) : "Non-digit character with ASCII code "+(int)array[a]+" was encountered.\n" jpayne@68: +"x="+x+"; char="+(char)array[a]+"\narray="+new String(array)+", start="+a+", stop="+b; jpayne@68: jpayne@68: //Multiply the old value by 10, then add the new 1's digit. jpayne@68: //This is because the text is assumed to be base-10, jpayne@68: //so each subsequent character will represent 1/10th the significance of the previous character. jpayne@68: r=(r*10)+x; jpayne@68: } jpayne@68: jpayne@68: //Change the unsigned value into a signed result, and return it. jpayne@68: return r*mult; jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param array Text jpayne@68: * @param a Index of first digit jpayne@68: * @param b Index after last digit (e.g., array.length) jpayne@68: * @return Parsed number jpayne@68: */ jpayne@68: public static int parseInt(String array, int a, int b){ jpayne@68: // assert(false) : Character.toString(array.charAt(a)); jpayne@68: assert(b>a); jpayne@68: int r=0; jpayne@68: final byte z='0'; jpayne@68: int mult=1; jpayne@68: if(array.charAt(a)=='-'){mult=-1; a++;} jpayne@68: for(; a=0) : x+" = "+array.charAt(a)+"\narray="+new String(array)+", start="+a+", stop="+b; jpayne@68: r=(r*10)+x; jpayne@68: } jpayne@68: return r*mult; jpayne@68: } jpayne@68: jpayne@68: public static long parseLong(byte[] array){return parseLong(array, 0, array.length);} jpayne@68: jpayne@68: public static long parseLong(byte[] array, int start){return parseLong(array, start, array.length);} jpayne@68: jpayne@68: /** jpayne@68: * @param array Text jpayne@68: * @param a Index of first digit jpayne@68: * @param b Index after last digit (e.g., array.length) jpayne@68: * @return Parsed number jpayne@68: */ jpayne@68: public static long parseLong(byte[] array, int a, int b){ jpayne@68: assert(b>a); jpayne@68: long r=0; jpayne@68: final byte z='0'; jpayne@68: long mult=1; jpayne@68: if(array[a]=='-'){mult=-1; a++;} jpayne@68: for(; a=0) : x+" = "+(char)array[a]+"\narray="+new String(array)+", start="+a+", stop="+b; jpayne@68: r=(r*10)+x; jpayne@68: } jpayne@68: return r*mult; jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param array Text jpayne@68: * @param a Index of first digit jpayne@68: * @param b Index after last digit (e.g., array.length) jpayne@68: * @return Parsed number jpayne@68: */ jpayne@68: public static long parseLong(String array, int a, int b){ jpayne@68: assert(b>a); jpayne@68: long r=0; jpayne@68: final byte z='0'; jpayne@68: long mult=1; jpayne@68: if(array.charAt(a)=='-'){mult=-1; a++;} jpayne@68: for(; a=0) : x+" = "+array.charAt(a)+"\narray="+new String(array)+", start="+a+", stop="+b; jpayne@68: r=(r*10)+x; jpayne@68: } jpayne@68: return r*mult; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: //Note: clen is optional, but allows poorly-formatted input like trailing whitespace jpayne@68: //Without clen ",,," would become {0,0,0,0} jpayne@68: public static long[] parseLongArray(String sub) { jpayne@68: if(sub==null || sub.length()<1){return null;} jpayne@68: long current=0; jpayne@68: // int clen=0; jpayne@68: LongList list=new LongList(min(8, 1+sub.length()/2)); jpayne@68: for(int i=0, len=sub.length(); i9){ jpayne@68: // System.err.println('A'); jpayne@68: //assert(clen>0); jpayne@68: list.add(current); jpayne@68: current=0; jpayne@68: // clen=0; jpayne@68: }else{ jpayne@68: // System.err.println('B'); jpayne@68: current=(current*10)+c; jpayne@68: // clen++; jpayne@68: } jpayne@68: // System.err.println("i="+i+", c="+c+", current="+current+", list="+list); jpayne@68: } jpayne@68: // if(clen>0){ jpayne@68: list.add(current); jpayne@68: // } jpayne@68: // assert(false) : "\n'"+sub+"'\n"+Arrays.toString(list.toArray()); jpayne@68: return list.toArray(); jpayne@68: } jpayne@68: jpayne@68: public static int parseZmw(String id){ jpayne@68: //Example: m54283_190403_183820/4194374/919_2614 jpayne@68: //Run ID is m54283_190403_183820 jpayne@68: //zmw ID is 4194374. jpayne@68: //Read start/stop coordinates are 919_2614 jpayne@68: int under=id.indexOf('_'); jpayne@68: int slash=id.indexOf('/'); jpayne@68: if(under<0 || slash<0){return -1;} jpayne@68: String[] split=id.split("/"); jpayne@68: String z=split[1]; jpayne@68: return Integer.parseInt(z); jpayne@68: } jpayne@68: jpayne@68: public static char parseSymbolToCharacter(String b){ jpayne@68: b=parseSymbol(b); jpayne@68: while(b.length()>1 && b.charAt(0)=='\\'){ jpayne@68: b=b.substring(1); jpayne@68: } jpayne@68: return b.charAt(0); jpayne@68: } jpayne@68: jpayne@68: public static String parseSymbol(String b){ jpayne@68: if(b==null || b.length()<2){return b;} jpayne@68: jpayne@68: //Convenience characters jpayne@68: if(b.equalsIgnoreCase("space")){ jpayne@68: return " "; jpayne@68: }else if(b.equalsIgnoreCase("tab")){ jpayne@68: return "\t"; jpayne@68: }else if(b.equalsIgnoreCase("whitespace")){ jpayne@68: return "\\s+"; jpayne@68: }else if(b.equalsIgnoreCase("pound")){ jpayne@68: return "#"; jpayne@68: }else if(b.equalsIgnoreCase("greaterthan")){ jpayne@68: return ">"; jpayne@68: }else if(b.equalsIgnoreCase("lessthan")){ jpayne@68: return "<"; jpayne@68: }else if(b.equalsIgnoreCase("equals")){ jpayne@68: return "="; jpayne@68: }else if(b.equalsIgnoreCase("colon")){ jpayne@68: return ":"; jpayne@68: }else if(b.equalsIgnoreCase("semicolon")){ jpayne@68: return ";"; jpayne@68: }else if(b.equalsIgnoreCase("bang")){ jpayne@68: return "!"; jpayne@68: }else if(b.equalsIgnoreCase("and") || b.equalsIgnoreCase("ampersand")){ jpayne@68: return "&"; jpayne@68: }else if(b.equalsIgnoreCase("quote") || b.equalsIgnoreCase("doublequote")){ jpayne@68: return "\""; jpayne@68: }else if(b.equalsIgnoreCase("singlequote") || b.equalsIgnoreCase("apostrophe")){ jpayne@68: return "'"; jpayne@68: } jpayne@68: jpayne@68: //Java meta characters jpayne@68: if(b.equalsIgnoreCase("backslash")){ jpayne@68: return "\\\\"; jpayne@68: }else if(b.equalsIgnoreCase("hat") || b.equalsIgnoreCase("caret")){ jpayne@68: return "\\^"; jpayne@68: }else if(b.equalsIgnoreCase("dollar")){ jpayne@68: return "\\$"; jpayne@68: }else if(b.equalsIgnoreCase("dot")){ jpayne@68: return "\\."; jpayne@68: }else if(b.equalsIgnoreCase("pipe") || b.equalsIgnoreCase("or")){ jpayne@68: return "\\|"; jpayne@68: }else if(b.equalsIgnoreCase("questionmark")){ jpayne@68: return "\\?"; jpayne@68: }else if(b.equalsIgnoreCase("star") || b.equalsIgnoreCase("asterisk")){ jpayne@68: return "\\*"; jpayne@68: }else if(b.equalsIgnoreCase("plus")){ jpayne@68: return "\\+"; jpayne@68: }else if(b.equalsIgnoreCase("openparen")){ jpayne@68: return "\\("; jpayne@68: }else if(b.equalsIgnoreCase("closeparen")){ jpayne@68: return "\\)"; jpayne@68: }else if(b.equalsIgnoreCase("opensquare")){ jpayne@68: return "\\["; jpayne@68: }else if(b.equalsIgnoreCase("opencurly")){ jpayne@68: return "\\{"; jpayne@68: } jpayne@68: jpayne@68: //No matches, return the literal jpayne@68: return b; jpayne@68: } jpayne@68: jpayne@68: public static byte[] parseRemap(String b){ jpayne@68: final byte[] remap; jpayne@68: if(b==null || ("f".equalsIgnoreCase(b) || "false".equalsIgnoreCase(b))){ jpayne@68: remap=null; jpayne@68: }else{ jpayne@68: assert((b.length()&1)==0) : "Length of remap argument must be even. No whitespace is allowed."; jpayne@68: jpayne@68: remap=new byte[128]; jpayne@68: for(int j=0; jy ? x : y;} jpayne@68: jpayne@68: }