/*******************************************************************************
- * Copyright (c) 2016 EfficiOS inc, Michael Jeanson
+ * Copyright (c) 2016 EfficiOS Inc., Michael Jeanson and others
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
package org.eclipse.tracecompass.common.core.tests.format;
+import static org.junit.Assert.assertEquals;
+
import java.text.Format;
+import java.text.ParseException;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.tracecompass.common.core.format.DecimalUnitFormat;
private static final @NonNull Format FORMATTER = new DecimalUnitFormat();
/**
- * Test an illegal argument
+ * Test format with an illegal argument
*/
@Test(expected = IllegalArgumentException.class)
- public void testException() {
- FORMATTER.format(new String("Toto"));
+ public void testFormatIllegalArgument() {
+ FORMATTER.format("Toto");
+ }
+
+ /**
+ * Test parsing a string that is not a number
+ * @throws ParseException if the string cannot be parsed
+ */
+ @Test(expected = ParseException.class)
+ public void testParseNotANumber() throws ParseException {
+ FORMATTER.parseObject("Toto");
+ }
+
+ /**
+ * Test parsing a number with a unit
+ * @throws ParseException if the string cannot be parsed
+ */
+ @Test
+ public void testParseWithUnit() throws ParseException {
+ FORMATTER.parseObject("1.2 s");
+ }
+
+ /**
+ * Test parsing a number with a prefix and a unit
+ * @throws ParseException if the string cannot be parsed
+ */
+ @Test
+ public void testParsePrefixWithUnitAndPrefix() throws ParseException {
+ assertEquals(0.0012, FORMATTER.parseObject("1.2 ms"));
+ }
+
+ /**
+ * Test parsing a special Double number with a prefix
+ * @throws ParseException if the string cannot be parsed
+ */
+ @Test
+ public void testParseSpecialWithPrefix() throws ParseException {
+ assertEquals(Double.POSITIVE_INFINITY, FORMATTER.parseObject("∞ k"));
+ assertEquals(Double.NEGATIVE_INFINITY, FORMATTER.parseObject("-∞ p"));
+ assertEquals(Double.NaN, FORMATTER.parseObject("�M"));
}
}
/*******************************************************************************
- * Copyright (c) 2016 EfficiOS inc, Michael Jeanson
+ * Copyright (c) 2016 EfficiOS Inc., Michael Jeanson and others
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
import static org.junit.Assert.assertEquals;
import java.text.Format;
+import java.text.ParseException;
import java.util.Arrays;
import org.eclipse.jdt.annotation.NonNull;
private static final @NonNull Format FORMATTER = new DecimalUnitFormat();
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 DecimalUnitFormatTest(@NonNull Number value, @NonNull String expected) {
- fNumValue = value;
- fExpected = expected;
+ public DecimalUnitFormatTest(@NonNull Number numValue, @NonNull String stringValue, @NonNull Number parseValue) {
+ fNumValue = numValue;
+ fStringValue = stringValue;
+ fParseValue = parseValue;
}
/**
@Parameters(name = "{index}: {0}")
public static Iterable<Object[]> getParameters() {
return Arrays.asList(new Object[][] {
- { 0, "0" },
- { 3, "3" },
- { 975, "975" },
- { 1000, "1 k" },
- { 4000, "4 k" },
- { -4000, "-4 k" },
- { 4000L, "4 k" },
- { 4000.0, "4 k" },
- { 12345678, "12.3 M" },
- { Integer.MAX_VALUE, "2.1 G" },
- { Integer.MIN_VALUE, "-2.1 G" },
- { Long.MAX_VALUE, "9223.4 P" },
- { 98765432.123456, "98.8 M" },
- { -98765432.123456, "-98.8 M" },
- { 555555555555L, "555.6 G" },
- { 555555555555555L, "555.6 T" },
- { 100100000, "100.1 M" },
- { 0.1, "100 m" },
- { 0.001, "1 m" },
- { 0.000001, "1 µ" },
- { 0.000000001, "1 n" },
- { 0.000000000001, "1 p" },
- { -0.04, "-40 m" },
- { 0.002, "2 m" },
- { 0.0555, "55.5 m" },
- { 0.0004928373928, "492.8 µ" },
- { 0.000000251, "251 n"},
- { 0.000000000043, "43 p"},
- { 0.000000045643, "45.6 n"},
- { Double.MAX_VALUE, "179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 P" },
- { Double.POSITIVE_INFINITY, "∞" },
- { Double.MIN_NORMAL, "0" },
- { Double.NEGATIVE_INFINITY, "-∞" },
- { Double.NaN, "�" },
+ { 3, "3", 3L },
+ { 5.6, "5.6", 5.6 },
+ { 1.234567, "1.2", 1.2 },
+ { 1.01, "1", 1L },
+ { 975, "975", 975L },
+ { 1000, "1 k", 1000L },
+ { 4000, "4 k", 4000L },
+ { -4000, "-4 k", -4000L },
+ { 4000L, "4 k", 4000L },
+ { 4000.0, "4 k", 4000L },
+ { 12345678, "12.3 M", 12300000L },
+ { Integer.MAX_VALUE, "2.1 G", 2100000000L },
+ { Integer.MIN_VALUE, "-2.1 G", -2100000000L },
+ { Long.MAX_VALUE, "9223.4 P", 9.2234E18 },
+ { 98765432.123456, "98.8 M", 98800000L },
+ { -98765432.123456, "-98.8 M", -98800000L },
+ { 555555555555L, "555.6 G", 555600000000L },
+ { 555555555555555L, "555.6 T", 555600000000000L },
+ { 100100000, "100.1 M", 100100000L },
+ { 0.1, "100 m", 0.1 },
+ { 0.001, "1 m", 0.001 },
+ { 0.000001, "1 µ", 0.000001 },
+ { 0.000000001, "1 n", 0.000000001 },
+ { 0.000000000001, "1 p", 0.000000000001 },
+ { 0.0000000000001, "0", 0L },
+ { -0.04, "-40 m", -0.04 },
+ { 0.002, "2 m", 0.002 },
+ { 0.0555, "55.5 m", 0.0555 },
+ { 0.0004928373928, "492.8 µ", 0.0004928 },
+ { 0.000000251, "251 n", 0.000000251 },
+ { 0.000000000043, "43 p", 0.000000000043 },
+ { 0.000000045643, "45.6 n", 0.0000000456 },
+ { Double.MAX_VALUE, "1.7976931348623157E308", 1.7976931348623157E308 },
+ { Double.POSITIVE_INFINITY, "∞", Double.POSITIVE_INFINITY },
+ { Double.MIN_NORMAL, "0", 0L },
+ { Double.NEGATIVE_INFINITY, "-∞", Double.NEGATIVE_INFINITY },
+ { Double.NaN, "�", Double.NaN }
});
}
*/
@Test
public void testFormat() {
- assertEquals("format value", fExpected, FORMATTER.format(fNumValue));
+ assertEquals("format value", fStringValue, FORMATTER.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, FORMATTER.parseObject(fStringValue));
}
}
/*******************************************************************************
- * Copyright (c) 2016 EfficiOS Inc., Michael Jeanson
+ * Copyright (c) 2016 EfficiOS Inc., Michael Jeanson and others
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
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 java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
/**
* Provides a formatter for decimal numbers with International System of Units
private static final double NANO = 0.000000001;
private static final double PICO = 0.000000000001;
+ /* Map of prefix to exponent */
+ private static final Map<String, Integer> PREFIX_MAP = ImmutableMap.<String, Integer>builder()
+ .put(KILO_PREFIX, +3)
+ .put(MEGA_PREFIX, +6)
+ .put(GIGA_PREFIX, +9)
+ .put(TERA_PREFIX, +12)
+ .put(PETA_PREFIX, +15)
+ .put(MILLI_PREFIX, -3)
+ .put(MICRO_PREFIX, -6)
+ .put(NANO_PREFIX, -9)
+ .put(PICO_PREFIX, -12)
+ .build();
private static final Format FORMAT = new DecimalFormat("#.#"); //$NON-NLS-1$
private final double fFactor;
}
if (abs >= 1) {
+ if (abs > Long.MAX_VALUE) {
+ return toAppendTo.append(num);
+ }
if (abs >= PETA) {
return toAppendTo.append(FORMAT.format(value / PETA)).append(' ').append(PETA_PREFIX);
}
throw new IllegalArgumentException("Cannot format given Object as a Number: " + obj); //$NON-NLS-1$
}
+ /**
+ * @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();
+ Integer exponent = null;
+ if (!unit.isEmpty()) {
+ String prefix = unit.substring(0, 1);
+ exponent = PREFIX_MAP.get(prefix);
+ }
+ if (exponent != null && Double.isFinite(number.doubleValue())) {
+ BigDecimal bd = new BigDecimal(number.toString());
+ bd = bd.movePointRight(exponent.intValue());
+ 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;
}
}