common: Support parsing in DataSizeWithUnitFormat
authorPatrick Tasse <patrick.tasse@gmail.com>
Thu, 1 Dec 2016 22:45:23 +0000 (17:45 -0500)
committerPatrick Tasse <patrick.tasse@gmail.com>
Fri, 2 Dec 2016 23:16:59 +0000 (18:16 -0500)
This allows parsing strings which represent a number with an optional
unit and binary prefix, such as "1 kB" (1024), "8 B" (8), "1.5M"
(1572864), "10 Gb" (10737418240), etc.

Change-Id: Iaaa222fb57b930f54ca9f0961b8240fe7b8e02ef
Signed-off-by: Patrick Tasse <patrick.tasse@gmail.com>
Reviewed-on: https://git.eclipse.org/r/86185
Reviewed-by: Hudson CI
Reviewed-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
common/org.eclipse.tracecompass.common.core.tests/src/org/eclipse/tracecompass/common/core/tests/format/DataSizeFormatTest.java
common/org.eclipse.tracecompass.common.core.tests/src/org/eclipse/tracecompass/common/core/tests/format/DataSpeedFormatTest.java
common/org.eclipse.tracecompass.common.core/src/org/eclipse/tracecompass/common/core/format/DataSizeWithUnitFormat.java

index 396acf4b1a97acef1b3d2fc3423034f3b80e964a..33708acc5450f35b3dd5810804c6fa69ee09d55e 100644 (file)
@@ -12,6 +12,7 @@ package org.eclipse.tracecompass.common.core.tests.format;
 import static org.junit.Assert.assertEquals;
 
 import java.text.Format;
+import java.text.ParseException;
 import java.util.Arrays;
 
 import org.eclipse.jdt.annotation.NonNull;
@@ -32,19 +33,23 @@ public class DataSizeFormatTest {
     private static final @NonNull Format FORMAT = DataSizeWithUnitFormat.getInstance();
 
     private final @NonNull Number fNumValue;
-    private final @NonNull String fExpected;
+    private final @NonNull String fStringValue;
+    private final @NonNull Number fParseValue;
 
     /**
      * Constructor
      *
-     * @param value
-     *            The numeric value to format
-     * @param expected
-     *            The expected formatted result
+     * @param numValue
+     *            The numeric value
+     * @param stringValue
+     *            The string value
+     * @param parseValue
+     *            The parse value of the string value
      */
-    public DataSizeFormatTest(@NonNull Number value, @NonNull String expected) {
-        fNumValue = value;
-        fExpected = expected;
+    public DataSizeFormatTest(@NonNull Number numValue, @NonNull String stringValue, @NonNull Number parseValue) {
+        fNumValue = numValue;
+        fStringValue = stringValue;
+        fParseValue = parseValue;
     }
 
     /**
@@ -53,25 +58,25 @@ public class DataSizeFormatTest {
     @Parameters(name = "{index}: {0}")
     public static Iterable<Object[]> getParameters() {
         return Arrays.asList(new Object[][] {
-                { 0, "0" },
-                { 3, "3 B" },
-                { 975, "975 B" },
-                { 1024, "1 KB" },
-                { 1024 * 1024, "1 MB" },
-                { 1024 * 1024 * 1024, "1 GB" },
-                { 1024L * 1024L * 1024L * 1024L, "1 TB" },
-                { 4096, "4 KB" },
-                { -4096, "-4 KB" },
-                { 4096L, "4 KB" },
-                { 4096.0, "4 KB" },
-                { 12345678, "11.774 MB" },
-                { Integer.MAX_VALUE, "2 GB" },
-                { Integer.MIN_VALUE, "-2 GB" },
-                { Long.MAX_VALUE, "8388608 TB" },
-                { 98765432.123456, "94.19 MB" },
-                { -98765432.123456, "-94.19 MB" },
-                { 555555555555L, "517.401 GB" },
-                { 555555555555555L, "505.275 TB" }
+                { 0, "0", 0L },
+                { 3, "3 B", 3L },
+                { 975, "975 B", 975L },
+                { 1024, "1 KB", 1024L },
+                { 1024 * 1024, "1 MB", 1024 * 1024L },
+                { 1024 * 1024 * 1024, "1 GB", 1024 * 1024 * 1024L },
+                { 1024L * 1024L * 1024L * 1024L, "1 TB", 1024 * 1024 * 1024 * 1024L },
+                { 4096, "4 KB", 4096L },
+                { -4096, "-4 KB", -4096L },
+                { 4096L, "4 KB", 4096L },
+                { 4096.0, "4 KB", 4096L },
+                { 12345678, "11.774 MB", 12345933.824 },
+                { Integer.MAX_VALUE, "2 GB", 2147483648L },
+                { Integer.MIN_VALUE, "-2 GB", -2147483648L },
+                { Long.MAX_VALUE, "8388608 TB", 9.223372036854775808E18 },
+                { 98765432.123456, "94.19 MB", 98765373.44 },
+                { -98765432.123456, "-94.19 MB", -98765373.44 },
+                { 555555555555L, "517.401 GB", 555555093479.424 },
+                { 555555555555555L, "505.275 TB", 555555737724518.4 }
         });
     }
 
@@ -89,6 +94,17 @@ public class DataSizeFormatTest {
      */
     @Test
     public void testFormat() {
-        assertEquals("format value", fExpected, getFormatter().format(fNumValue));
+        assertEquals("format value", fStringValue, getFormatter().format(fNumValue));
+    }
+
+    /**
+     * Test the {@link Format#parseObject(String)} method
+     *
+     * @throws ParseException
+     *             if the string cannot be parsed
+     */
+    @Test
+    public void testParseObject() throws ParseException {
+        assertEquals("parseObject value", fParseValue, getFormatter().parseObject(fStringValue));
     }
 }
index e3b70ef4ce6c711f0bd9243a4ec6bffd60a4f0ab..248ed9357aa590f34e0d27ccaf7ef419f7c2230f 100644 (file)
@@ -27,13 +27,15 @@ public class DataSpeedFormatTest extends DataSizeFormatTest {
     /**
      * Constructor
      *
-     * @param value
-     *            The numeric value to format
-     * @param expected
-     *            The expected formatted result
+     * @param numValue
+     *            The numeric value
+     * @param stringValue
+     *            The string value
+     * @param parseValue
+     *            The parse value of the string value
      */
-    public DataSpeedFormatTest(@NonNull Number value, @NonNull String expected) {
-        super(value, expected + PER_SECOND);
+    public DataSpeedFormatTest(@NonNull Number numValue, @NonNull String stringValue, @NonNull Number parseValue) {
+        super(numValue, stringValue + PER_SECOND, parseValue);
     }
 
     @Override
index 72f8575041aa9e1a8cca171f06a322aa025bbe9d..489819ffc900e7d12fdaf7a743d96f2c09a94207 100644 (file)
@@ -9,9 +9,11 @@
 
 package org.eclipse.tracecompass.common.core.format;
 
+import java.math.BigDecimal;
 import java.text.DecimalFormat;
 import java.text.FieldPosition;
 import java.text.Format;
+import java.text.NumberFormat;
 import java.text.ParsePosition;
 
 import org.eclipse.jdt.annotation.NonNull;
@@ -30,10 +32,10 @@ public class DataSizeWithUnitFormat extends Format {
 
     private static final long serialVersionUID = 3934127385682676804L;
     private static final String B = "B"; //$NON-NLS-1$
-    private static final String KB = "KB"; //$NON-NLS-1$
-    private static final String MB = "MB"; //$NON-NLS-1$
-    private static final String GB = "GB"; //$NON-NLS-1$
-    private static final String TB = "TB"; //$NON-NLS-1$
+    private static final String K = "K"; //$NON-NLS-1$
+    private static final String M = "M"; //$NON-NLS-1$
+    private static final String G = "G"; //$NON-NLS-1$
+    private static final String T = "T"; //$NON-NLS-1$
     private static final long KILO = 1024;
     private static final Format FORMAT = new DecimalFormat("#.###"); //$NON-NLS-1$
 
@@ -63,24 +65,53 @@ public class DataSizeWithUnitFormat extends Format {
                 return toAppendTo.append("0"); //$NON-NLS-1$
             }
             if (abs >= KILO * KILO * KILO * KILO) {
-                return toAppendTo.append(FORMAT.format(value / (KILO * KILO * KILO * KILO))).append(' ').append(TB);
+                return toAppendTo.append(FORMAT.format(value / (KILO * KILO * KILO * KILO))).append(' ').append(T).append(B);
             }
             if (abs >= KILO * KILO * KILO) {
-                return toAppendTo.append(FORMAT.format(value / (KILO * KILO * KILO))).append(' ').append(GB);
+                return toAppendTo.append(FORMAT.format(value / (KILO * KILO * KILO))).append(' ').append(G).append(B);
             }
             if (abs >= KILO * KILO) {
-                return toAppendTo.append(FORMAT.format(value / (KILO * KILO))).append(' ').append(MB);
+                return toAppendTo.append(FORMAT.format(value / (KILO * KILO))).append(' ').append(M).append(B);
             }
             if (abs >= KILO) {
-                return toAppendTo.append(FORMAT.format(value / (KILO))).append(' ').append(KB);
+                return toAppendTo.append(FORMAT.format(value / (KILO))).append(' ').append(K).append(B);
             }
             return toAppendTo.append(FORMAT.format(value)).append(' ').append(B);
         }
         return toAppendTo.append(obj);
     }
 
+    /**
+     * @since 2.1
+     */
     @Override
-    public Object parseObject(String source, ParsePosition pos) {
-        return source == null ? "" : source; //$NON-NLS-1$
+    public Number parseObject(String source, ParsePosition pos) {
+        Number number = NumberFormat.getInstance().parse(source, pos);
+        if (number == null) {
+            return null;
+        }
+        String unit = source.substring(pos.getIndex()).trim().toUpperCase();
+        long multiplier = 1;
+        if (!unit.isEmpty()) {
+            if (unit.startsWith(K)) {
+                multiplier = KILO;
+            } else if (unit.startsWith(M)) {
+                multiplier = KILO * KILO;
+            } else if (unit.startsWith(G)) {
+                multiplier = KILO * KILO * KILO;
+            } else if (unit.startsWith(T)) {
+                multiplier = KILO * KILO * KILO * KILO;
+            }
+        }
+        if (multiplier != 1 && Double.isFinite(number.doubleValue())) {
+            BigDecimal bd = new BigDecimal(number.toString());
+            bd = bd.multiply(BigDecimal.valueOf(multiplier));
+            if (bd.remainder(BigDecimal.ONE).equals(BigDecimal.ZERO) &&
+                    bd.abs().compareTo(new BigDecimal(Long.MAX_VALUE)) < 0) {
+                return bd.longValue();
+            }
+            return bd.doubleValue();
+        }
+        return number;
     }
 }
This page took 0.029327 seconds and 5 git commands to generate.