Added functionality to AsmNumberUtil
authorFabian Stemmler <stemmler@in.tum.de>
Sun, 25 Aug 2019 15:20:10 +0000 (17:20 +0200)
committerFabian Stemmler <stemmler@in.tum.de>
Sun, 25 Aug 2019 15:20:10 +0000 (17:20 +0200)
BigIntegers can now be formatted as any of the NumberTypes
A String can now be parsed as a BigInteger of a given NumberType
It can now be checked, if a String is a prefix of a valid number

net.mograsim.plugin.core/src/net/mograsim/plugin/asm/AsmNumberUtil.java

index 264d447..8ed3ef3 100644 (file)
@@ -3,6 +3,7 @@ package net.mograsim.plugin.asm;
 import static java.lang.String.format;\r
 \r
 import java.math.BigInteger;\r
+import java.util.regex.Matcher;\r
 import java.util.regex.Pattern;\r
 \r
 public final class AsmNumberUtil\r
@@ -18,13 +19,25 @@ public final class AsmNumberUtil
        private static final String octPat = "((?:[0-7]+_)*[0-7]+)";\r
        private static final String decPat = "((?:[0-9]+_)*[0-9]+)";\r
        private static final String hexPat = "((?:[0-9a-f]+_)*[0-9a-f]+)";\r
-       static final Pattern numberBin = Pattern.compile(format("%1$s0b%2$s|%1$s%2$sb", sgnPat, binPat), Pattern.CASE_INSENSITIVE);\r
-       static final Pattern numberOct = Pattern.compile(format("%s%sq", sgnPat, octPat), Pattern.CASE_INSENSITIVE);\r
-       static final Pattern numberDec = Pattern.compile(format("%s%s", sgnPat, decPat));\r
-       static final Pattern numberHex = Pattern.compile(format("%1$s0x%2$s|%1$s%2$sh", sgnPat, hexPat), Pattern.CASE_INSENSITIVE);\r
+\r
+       private static final String preferredBinPat = "%1$s0b%2$s";\r
+       private static final String preferredOctPat = "%s%sq";\r
+       private static final String preferredDecPat = "%s%s";\r
+       private static final String preferredHexPat = "%1$s0x%2$s";\r
+\r
+       static final Pattern numberBin = Pattern.compile(format(preferredBinPat + "|%1$s%2$sb", sgnPat, binPat), Pattern.CASE_INSENSITIVE);\r
+       static final Pattern numberOct = Pattern.compile(format(preferredOctPat, sgnPat, octPat), Pattern.CASE_INSENSITIVE);\r
+       static final Pattern numberDec = Pattern.compile(format(preferredDecPat, sgnPat, decPat));\r
+       static final Pattern numberHex = Pattern.compile(format(preferredHexPat + "|%1$s%2$sh", sgnPat, hexPat), Pattern.CASE_INSENSITIVE);\r
        static final Pattern numberFloat = Pattern.compile(format("%1$s%2$s(?:\\.%2$s)?(?:e%1$s%2$s)?", sgnPat, decPat),\r
                        Pattern.CASE_INSENSITIVE);\r
 \r
+       public static boolean isPrefix(CharSequence cs, Pattern p)\r
+       {\r
+               Matcher m = p.matcher(cs);\r
+               return m.matches() || m.hitEnd();\r
+       }\r
+\r
        public static boolean isBinary(CharSequence cs)\r
        {\r
                return numberBin.matcher(cs).matches();\r
@@ -113,11 +126,40 @@ public final class AsmNumberUtil
                return NumberType.NONE;\r
        }\r
 \r
+       /**\r
+        * 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\r
+        * prefix of multiple different {@link NumberType}s, the one with the smallest radix is returned. If no valid {@link NumberType} is\r
+        * found, {@link NumberType#NONE} is returned.\r
+        * \r
+        * @param cs The potential prefix\r
+        * @return The type the {@link CharSequence} is a prefix of\r
+        */\r
+       public static NumberType prefixOfType(CharSequence cs)\r
+       {\r
+               if (isPrefix(cs, numberBin))\r
+                       return NumberType.BINARY;\r
+               if (isPrefix(cs, numberOct))\r
+                       return NumberType.OCTAL;\r
+               if (isPrefix(cs, numberDec))\r
+                       return NumberType.DECIMAL;\r
+               if (isPrefix(cs, numberHex))\r
+                       return NumberType.HEXADECIMAL;\r
+               if (isPrefix(cs, numberFloat))\r
+                       return NumberType.FLOATINGPOINT;\r
+               return NumberType.NONE;\r
+       }\r
+\r
        private static CharSequence extractSignAndDigits(NumberType type, CharSequence cs)\r
        {\r
                return type.numberPattern.matcher(cs).replaceAll("$1$2").replaceAll("_", "");\r
        }\r
 \r
+       /**\r
+        * Computes the {@link BigInteger} value of a {@link CharSequence}, by determining the {@link NumberType} and parsing the number with\r
+        * the determined radix.\r
+        * \r
+        * @throws NumberFormatException if the {@link CharSequence} does not match any of the expected number patterns\r
+        */\r
        public static BigInteger valueOf(CharSequence cs)\r
        {\r
                NumberType type = getType(cs);\r
@@ -126,13 +168,39 @@ public final class AsmNumberUtil
                return new BigInteger(extractSignAndDigits(type, cs).toString(), type.radix);\r
        }\r
 \r
+       /**\r
+        * Formats a {@link BigInteger} in accordance with the pattern associated with the supplied {@link NumberType}\r
+        */\r
+       public static String toString(BigInteger number, NumberType type)\r
+       {\r
+               String pattern;\r
+               switch (type)\r
+               {\r
+               case BINARY:\r
+                       pattern = preferredBinPat;\r
+                       break;\r
+               case OCTAL:\r
+                       pattern = preferredOctPat;\r
+                       break;\r
+               default:\r
+               case DECIMAL:\r
+                       pattern = preferredDecPat;\r
+                       break;\r
+               case HEXADECIMAL:\r
+                       pattern = preferredHexPat;\r
+               }\r
+               if (number.signum() < 0)\r
+                       return String.format(pattern, "-", number.abs().toString(type.radix));\r
+               return String.format(pattern, "", number.toString(type.radix));\r
+       }\r
+\r
        public enum NumberType\r
        {\r
                NONE(-1, null), BINARY(2, AsmNumberUtil.numberBin), OCTAL(8, AsmNumberUtil.numberOct), DECIMAL(10, AsmNumberUtil.numberDec),\r
                HEXADECIMAL(16, AsmNumberUtil.numberHex), FLOATINGPOINT(10, AsmNumberUtil.numberFloat);\r
 \r
                public final int radix;\r
-               private final Pattern numberPattern;\r
+               final Pattern numberPattern;\r
 \r
                NumberType(int radix, Pattern numberPattern)\r
                {\r