X-Git-Url: https://mograsim.net/gitweb/?a=blobdiff_plain;f=net.mograsim.plugin.core%2Fsrc%2Fnet%2Fmograsim%2Fplugin%2Fasm%2FAsmNumberUtil.java;h=580c32494be7f644b24d8dc5f49447e33924f4f2;hb=a712f854c6666e2b42a277485f1fd407cf3e72ef;hp=8a9f8a3bf24e57e4f69e963465fdc5e545419bb4;hpb=f14ea37d69488dd51518a36413af7176916b8bd7;p=Mograsim.git diff --git a/net.mograsim.plugin.core/src/net/mograsim/plugin/asm/AsmNumberUtil.java b/net.mograsim.plugin.core/src/net/mograsim/plugin/asm/AsmNumberUtil.java index 8a9f8a3b..580c3249 100644 --- a/net.mograsim.plugin.core/src/net/mograsim/plugin/asm/AsmNumberUtil.java +++ b/net.mograsim.plugin.core/src/net/mograsim/plugin/asm/AsmNumberUtil.java @@ -2,6 +2,8 @@ package net.mograsim.plugin.asm; import static java.lang.String.format; +import java.math.BigInteger; +import java.util.regex.Matcher; import java.util.regex.Pattern; public final class AsmNumberUtil @@ -12,18 +14,30 @@ public final class AsmNumberUtil } - private static final String sgnPat = "[-+]?"; - private static final String binPat = "(?:[01]+_)*[01]+"; - private static final String octPat = "(?:[0-7]+_)*[0-7]+"; - private static final String decPat = "(?:[0-9]+_)*[0-9]+"; - private static final String hexPat = "(?:[0-9a-f]+_)*[0-9a-f]+"; - static final Pattern numberBin = Pattern.compile(format("%1$s0b%2$s|%1$s%2$sb", sgnPat, binPat), Pattern.CASE_INSENSITIVE); - static final Pattern numberOct = Pattern.compile(format("%s%sq", sgnPat, octPat), Pattern.CASE_INSENSITIVE); - static final Pattern numberDec = Pattern.compile(format("%s%s", sgnPat, decPat)); - static final Pattern numberHex = Pattern.compile(format("%1$s0x%2$s|%1$s%2$sh", sgnPat, hexPat), Pattern.CASE_INSENSITIVE); + private static final String sgnPat = "([-+]?)"; + private static final String binPat = "((?:[01]+_)*[01]+)"; + private static final String octPat = "((?:[0-7]+_)*[0-7]+)"; + private static final String decPat = "((?:[0-9]+_)*[0-9]+)"; + private static final String hexPat = "((?:[0-9a-f]+_)*[0-9a-f]+)"; + + private static final String preferredBinPat = "%1$s0b%2$s"; + private static final String preferredOctPat = "%s%sq"; + private static final String preferredDecPat = "%s%s"; + private static final String preferredHexPat = "%1$s0x%2$s"; + + static final Pattern numberBin = Pattern.compile(format(preferredBinPat + "|%1$s%2$sb", sgnPat, binPat), Pattern.CASE_INSENSITIVE); + static final Pattern numberOct = Pattern.compile(format(preferredOctPat, sgnPat, octPat), Pattern.CASE_INSENSITIVE); + static final Pattern numberDec = Pattern.compile(format(preferredDecPat, sgnPat, decPat)); + static final Pattern numberHex = Pattern.compile(format(preferredHexPat + "|%1$s%2$sh", sgnPat, hexPat), Pattern.CASE_INSENSITIVE); static final Pattern numberFloat = Pattern.compile(format("%1$s%2$s(?:\\.%2$s)?(?:e%1$s%2$s)?", sgnPat, decPat), Pattern.CASE_INSENSITIVE); + public static boolean isPrefix(CharSequence cs, Pattern p) + { + Matcher m = p.matcher(cs); + return m.matches() || m.hitEnd(); + } + public static boolean isBinary(CharSequence cs) { return numberBin.matcher(cs).matches(); @@ -112,8 +126,86 @@ public final class AsmNumberUtil return NumberType.NONE; } + /** + * Checks if the {@link CharSequence} is a prefix of a valid number, and returns the NumberType it is a prefix of. If a String is a + * prefix of multiple different {@link NumberType}s, the one with the smallest radix is returned. If no valid {@link NumberType} is + * found, {@link NumberType#NONE} is returned. + * + * @param cs The potential prefix + * @return The type the {@link CharSequence} is a prefix of + */ + public static NumberType prefixOfType(CharSequence cs) + { + if (isPrefix(cs, numberBin)) + return NumberType.BINARY; + if (isPrefix(cs, numberOct)) + return NumberType.OCTAL; + if (isPrefix(cs, numberDec)) + return NumberType.DECIMAL; + if (isPrefix(cs, numberHex)) + return NumberType.HEXADECIMAL; + if (isPrefix(cs, numberFloat)) + return NumberType.FLOATINGPOINT; + return NumberType.NONE; + } + + private static CharSequence extractSignAndDigits(NumberType type, CharSequence cs) + { + return type.numberPattern.matcher(cs).replaceAll("$1$2").replaceAll("_", ""); + } + + /** + * Computes the {@link BigInteger} value of a {@link CharSequence}, by determining the {@link NumberType} and parsing the number with + * the determined radix. + * + * @throws NumberFormatException if the {@link CharSequence} does not match any of the expected number patterns + */ + public static BigInteger valueOf(CharSequence cs) + { + NumberType type = getType(cs); + if (NumberType.NONE.equals(type)) + throw new NumberFormatException(); + return new BigInteger(extractSignAndDigits(type, cs).toString(), type.radix); + } + + /** + * Formats a {@link BigInteger} in accordance with the pattern associated with the supplied {@link NumberType} + */ + public static String toString(BigInteger number, NumberType type) + { + String pattern; + switch (type) + { + case BINARY: + pattern = preferredBinPat; + break; + case OCTAL: + pattern = preferredOctPat; + break; + default: + case DECIMAL: + pattern = preferredDecPat; + break; + case HEXADECIMAL: + pattern = preferredHexPat; + } + if (number.signum() < 0) + return String.format(pattern, "-", number.abs().toString(type.radix)); + return String.format(pattern, "", number.toString(type.radix)); + } + public enum NumberType { - NONE, BINARY, OCTAL, DECIMAL, HEXADECIMAL, FLOATINGPOINT + NONE(-1, null), BINARY(2, AsmNumberUtil.numberBin), OCTAL(8, AsmNumberUtil.numberOct), DECIMAL(10, AsmNumberUtil.numberDec), + HEXADECIMAL(16, AsmNumberUtil.numberHex), FLOATINGPOINT(10, AsmNumberUtil.numberFloat); + + public final int radix; + final Pattern numberPattern; + + NumberType(int radix, Pattern numberPattern) + { + this.radix = radix; + this.numberPattern = numberPattern; + } } }