From a190d292ce85b7f96581bf8f197afe2e944af490 Mon Sep 17 00:00:00 2001 From: Abraham Wolk Date: Fri, 12 Dec 2025 09:34:56 +0100 Subject: [PATCH 1/3] CSSTUDIO-3605 Always use the type "long" when converting to hexadecimal notation. --- .../java/org/phoebus/ui/vtype/FormatOptionHandler.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java b/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java index 2cb6097538..ddd8fd0585 100644 --- a/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java +++ b/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java @@ -219,10 +219,9 @@ private static String formatNumber(final Number value, final Display display, if (option == FormatOption.HEX) { final StringBuilder buf = new StringBuilder(); - if (precision <= 8) - buf.append(Integer.toHexString(value.intValue()).toUpperCase()); - else - buf.append(Long.toHexString(value.longValue()).toUpperCase()); + long longValue = value.longValue(); + String hexString = Long.toHexString(longValue); + buf.append(hexString.toUpperCase()); for (int i=buf.length(); i Date: Mon, 15 Dec 2025 09:41:44 +0100 Subject: [PATCH 2/3] CSSTUDIO-3605 Bugfix: Avoid sign extension when converting numbers to the type Long. --- .../phoebus/ui/vtype/FormatOptionHandler.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java b/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java index ddd8fd0585..6f654f6e8b 100644 --- a/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java +++ b/core/ui/src/main/java/org/phoebus/ui/vtype/FormatOptionHandler.java @@ -18,6 +18,10 @@ import java.util.logging.Logger; import org.epics.util.array.ListNumber; +import org.epics.util.number.UByte; +import org.epics.util.number.UInteger; +import org.epics.util.number.ULong; +import org.epics.util.number.UShort; import org.epics.vtype.Display; import org.epics.vtype.DisplayProvider; import org.epics.vtype.VBoolean; @@ -219,7 +223,30 @@ private static String formatNumber(final Number value, final Display display, if (option == FormatOption.HEX) { final StringBuilder buf = new StringBuilder(); - long longValue = value.longValue(); + long longValue; + if (value instanceof Byte valueByte) { + longValue = Byte.toUnsignedLong(valueByte); + } else if (value instanceof Short valueShort) { + longValue = Short.toUnsignedLong(valueShort); + } else if (value instanceof Integer valueInt) { + longValue = Integer.toUnsignedLong(valueInt); + } else if (value instanceof Long valueLong) { + longValue = valueLong; + } else if (value instanceof Float valueFloat) { + longValue = valueFloat.longValue(); + } else if (value instanceof Double valueDouble) { + longValue = valueDouble.longValue(); + } else if (value instanceof UByte valueUByte) { + longValue = valueUByte.longValue(); + } else if (value instanceof UShort valueUShort) { + longValue = valueUShort.longValue(); + } else if (value instanceof UInteger valueUInteger) { + longValue = valueUInteger.longValue(); + } else if (value instanceof ULong valueULong) { + longValue = valueULong.longValue(); + } else { + longValue = value.longValue(); + } String hexString = Long.toHexString(longValue); buf.append(hexString.toUpperCase()); for (int i=buf.length(); i Date: Mon, 15 Dec 2025 09:42:34 +0100 Subject: [PATCH 3/3] CSSTUDIO-3605 Add test cases. --- .../ui/vtype/FormatOptionHandlerTest.java | 260 +++++++++++++++++- 1 file changed, 247 insertions(+), 13 deletions(-) diff --git a/core/ui/src/test/java/org/phoebus/ui/vtype/FormatOptionHandlerTest.java b/core/ui/src/test/java/org/phoebus/ui/vtype/FormatOptionHandlerTest.java index d4a0625650..3e4072e915 100644 --- a/core/ui/src/test/java/org/phoebus/ui/vtype/FormatOptionHandlerTest.java +++ b/core/ui/src/test/java/org/phoebus/ui/vtype/FormatOptionHandlerTest.java @@ -15,14 +15,22 @@ import org.epics.vtype.Display; import org.epics.vtype.EnumDisplay; import org.epics.vtype.Time; +import org.epics.vtype.VByte; import org.epics.vtype.VDouble; import org.epics.vtype.VEnum; +import org.epics.vtype.VFloat; +import org.epics.vtype.VInt; import org.epics.vtype.VIntArray; import org.epics.vtype.VLong; import org.epics.vtype.VNumberArray; +import org.epics.vtype.VShort; import org.epics.vtype.VString; import org.epics.vtype.VStringArray; import org.epics.vtype.VType; +import org.epics.vtype.VUByte; +import org.epics.vtype.VUInt; +import org.epics.vtype.VULong; +import org.epics.vtype.VUShort; import org.junit.jupiter.api.Test; import java.text.DecimalFormat; @@ -167,19 +175,245 @@ public void testEngineering() @Test public void testHexFormat() { - VType number = VDouble.of(65535.0, Alarm.none(), Time.now(), display); - - String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); - System.out.println(text); - assertThat(text, equalTo("0xFFFF V")); - - text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); - System.out.println(text); - assertThat(text, equalTo("0x0000FFFF V")); - - text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); - System.out.println(text); - assertThat(text, equalTo("0x000000000000FFFF V")); + { + VType number = VDouble.of(65535.0, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x0000FFFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x000000000000FFFF V")); + } + + { + // Test with VDouble representing 0xFFFFFFFF + VType number = VDouble.of(4294967295.0, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000FFFFFFFF V")); + } + + { + // Test with VFloat representing 0xFFFF + VType number = VFloat.of(65535.0, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x0000FFFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x000000000000FFFF V")); + } + + { + // Test with VInt representing 0x00 + VType number = VInt.of(0x00, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0x0000 V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000 V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x0000000000000000 V")); + } + + { + // Test with VByte representing 0xFF + VType number = VByte.of(0xFF, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 2, true); + System.out.println(text); + assertThat(text, equalTo("0xFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0x00FF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x000000FF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000000000FF V")); + } + + { + // Test with VByte representing 0xFF + VType number = VUByte.of(0xFF, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 2, true); + System.out.println(text); + assertThat(text, equalTo("0xFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0x00FF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x000000FF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000000000FF V")); + } + + { + // Test with VShort representing 0xFFAA + VType number = VShort.of(0xFFAA, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 2, true); + System.out.println(text); + assertThat(text, equalTo("0xFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x0000FFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x000000000000FFAA V")); + } + + { + // Test with VUShort representing 0xFFAA + VType number = VUShort.of(0xFFAA, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 2, true); + System.out.println(text); + assertThat(text, equalTo("0xFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x0000FFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x000000000000FFAA V")); + } + + { + // Test with VInt representing 0xFF + VType number = VInt.of(0xFF, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 2, true); + System.out.println(text); + assertThat(text, equalTo("0xFF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0x00FF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0x000000FF V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000000000FF V")); + } + + { + // Test with VInt representing 0xFFFFFFAA + VType number = VInt.of(0xFFFFFFAA, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000FFFFFFAA V")); + } + + { + // Test with VUInt representing 0xFFFFFFAA + VType number = VUInt.of(0xFFFFFFAA, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0x00000000FFFFFFAA V")); + } + + { + // Test with VLong representing 0xFFFFFFAA + VType number = VLong.of(0xFFFFFFFFFFFFFFAAL, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFFFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFFFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFFFFFFFFAA V")); + } + + { + // Test with VULong representing 0xFFFFFFAA + VType number = VULong.of(0xFFFFFFFFFFFFFFAAL, Alarm.none(), Time.now(), display); + + String text = FormatOptionHandler.format(number, FormatOption.HEX, 4, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFFFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 8, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFFFFFFFFAA V")); + + text = FormatOptionHandler.format(number, FormatOption.HEX, 16, true); + System.out.println(text); + assertThat(text, equalTo("0xFFFFFFFFFFFFFFAA V")); + } } @Test