1 package net.mograsim.plugin.asm;
3 import static java.lang.String.format;
5 import java.math.BigInteger;
6 import java.util.regex.Pattern;
8 public final class AsmNumberUtil
11 private AsmNumberUtil()
16 private static final String sgnPat = "([-+]?)";
17 private static final String binPat = "((?:[01]+_)*[01]+)";
18 private static final String octPat = "((?:[0-7]+_)*[0-7]+)";
19 private static final String decPat = "((?:[0-9]+_)*[0-9]+)";
20 private static final String hexPat = "((?:[0-9a-f]+_)*[0-9a-f]+)";
21 static final Pattern numberBin = Pattern.compile(format("%1$s0b%2$s|%1$s%2$sb", sgnPat, binPat), Pattern.CASE_INSENSITIVE);
22 static final Pattern numberOct = Pattern.compile(format("%s%sq", sgnPat, octPat), Pattern.CASE_INSENSITIVE);
23 static final Pattern numberDec = Pattern.compile(format("%s%s", sgnPat, decPat));
24 static final Pattern numberHex = Pattern.compile(format("%1$s0x%2$s|%1$s%2$sh", sgnPat, hexPat), Pattern.CASE_INSENSITIVE);
25 static final Pattern numberFloat = Pattern.compile(format("%1$s%2$s(?:\\.%2$s)?(?:e%1$s%2$s)?", sgnPat, decPat),
26 Pattern.CASE_INSENSITIVE);
28 public static boolean isBinary(CharSequence cs)
30 return numberBin.matcher(cs).matches();
33 public static boolean isOctal(CharSequence cs)
35 return numberOct.matcher(cs).matches();
38 public static boolean isDecimal(CharSequence cs)
40 return numberDec.matcher(cs).matches();
43 public static boolean isHexadecimal(CharSequence cs)
45 return numberHex.matcher(cs).matches();
48 public static boolean isFloatingPoint(CharSequence cs)
50 return numberFloat.matcher(cs).matches();
53 public static boolean isNumber(CharSequence cs)
55 return getType(cs) != NumberType.NONE;
58 public static boolean quickCheckForNumber(CharSequence cs)
60 if (cs.length() == 0 || !isStart(cs.charAt(0)))
62 return cs.length() == 1 || isPart(cs.charAt(1));
65 public static boolean isStart(int c)
67 return isDigit(c) || c == '+' || c == '-';
70 public static boolean isDigit(int c)
72 return ('0' <= c && c <= '9') || ('A' <= c && c <= 'F') || ('a' <= c && c <= 'f');
75 public static boolean isPart(int c)
77 return isDigit(c) || isMarker(Character.toLowerCase(c));
80 public static boolean isMarker(int lowerCase)
99 public static NumberType getType(CharSequence cs)
101 if (!quickCheckForNumber(cs))
102 return NumberType.NONE;
104 return NumberType.DECIMAL;
105 if (isHexadecimal(cs))
106 return NumberType.HEXADECIMAL;
108 return NumberType.BINARY;
110 return NumberType.OCTAL;
111 if (isFloatingPoint(cs))
112 return NumberType.FLOATINGPOINT;
113 return NumberType.NONE;
116 private static CharSequence extractSignAndDigits(NumberType type, CharSequence cs)
118 return type.numberPattern.matcher(cs).replaceAll("$1$2").replaceAll("_", "");
121 public static BigInteger valueOf(CharSequence cs)
123 NumberType type = getType(cs);
124 if (NumberType.NONE.equals(type))
125 throw new NumberFormatException();
126 return new BigInteger(extractSignAndDigits(type, cs).toString(), type.radix);
129 public enum NumberType
131 NONE(-1, null), BINARY(2, AsmNumberUtil.numberBin), OCTAL(8, AsmNumberUtil.numberOct), DECIMAL(10, AsmNumberUtil.numberDec),
132 HEXADECIMAL(16, AsmNumberUtil.numberHex), FLOATINGPOINT(10, AsmNumberUtil.numberFloat);
134 public final int radix;
135 private final Pattern numberPattern;
137 NumberType(int radix, Pattern numberPattern)
140 this.numberPattern = numberPattern;