Thursday, August 17, 2006

Parsing and verifying hex, octal and decimal numbers...

How to parse a number that might be octal, decimal or hexadecimal. Numbers like 0xFF, 0x1e, 077, -123, -0x12, -066. This must have been solved a million times, and here's my version:

Thank you for all the comments! My code is stupid! Use Long.decode(numberString).longValue() Instead!
String sign="";
int base=10;
if(numberString.startsWith("-")) {
sign="-";
numberString=numberString.substring(1);
}
if(numberString.startsWith("0x")) {
numberString=numberString.substring(2);
base=16;
} else if(numberString.startsWith("0") && numberString.length()>1) {
numberString=numberString.substring(1);
base=8;
}
return Long.parseLong(sign+numberString,base);


OK, and here is my VerifyListener:
class NumberVerifyer implements VerifyListener {
final boolean fSigned;
NumberVerifyer(boolean signed) {
fSigned=signed;
}
public void verifyText(VerifyEvent e) {
Text text = ((Text)e.widget);
StringBuffer fulltext = new StringBuffer(text.getText());
fulltext.replace(e.start, e.end, e.text);
String sign=""; //$NON-NLS-1$
if(fSigned)
sign="-?"; //$NON-NLS-1$
e.doit = fulltext.toString().matches(sign+"(0?|[1-9][0-9]*|0x[0-9a-fA-F]*|0[0-7]+)"); //$NON-NLS-1$
}
}

7 comments:

  1. Um. Long#decode(String) is exactly for parsing a String to a long taking a prefix as the base indicator into consideration. It works almost as your implementation but also consideres "0X" (upcase X) and "#" as hex prefixes.

    marko (ms@datenreisender.de)

    ReplyDelete
  2. Oh man, never write even trivial code without testcase. I just found a fatal error in my number parser: it would not parse the simple string "0". The fix is to add
    && numberString.length()>1
    to the octal case. I fixed the blog entry, but at planeteclipse.org the wrong version is still hanging around....

    ReplyDelete
  3. FYI, you can use Long.decode to do this.

    ReplyDelete
  4. For the string to int conversion, you might also consider using java.lang.Long.decode() or Integer.decode() :-)

    ReplyDelete
  5. How about just using "return Long.decode(numberString).longValue()"...

    ReplyDelete
  6. Why bother setting the string to what it is already? Just set the doit flag.

    ReplyDelete
  7. Now we can use StringBuilder in place of StringBuffer, though I see its quite old article and I am not sure whether StringBuilder would have been available that time.

    Thanks
    5 tips on writing equals method in Java

    ReplyDelete